<?xml version="1.0" encoding="utf-8"?><testsuites name="pytest tests"><testsuite name="pytest" errors="4" failures="2" skipped="14" tests="168" time="1479.198" timestamp="2026-10-30T12:45:58.720157+00:00" hostname="maas-group-test-nn85n-e2e-maas-openshift-pod"><testcase classname="tests.test_aitenant_lifecycle.TestAITenantLifecycle" name="test_aitenant_delete_cleans_maas_resources_and_preserves_user_objects" time="44.330" /><testcase classname="tests.test_aitenant_lifecycle.TestAITenantLifecycle" name="test_default_aitenant_bootstraps_maas_tenant_config_without_gateway_mutation" time="2.139" /><testcase classname="tests.test_aitenant_lifecycle.TestAITenantLifecycle" name="test_aitenant_migrates_and_removes_legacy_tenant" time="39.084" /><testcase classname="tests.test_aitenant_lifecycle.TestAITenantLifecycle" name="test_aitenant_rejected_outside_ai_tenants_namespace" time="8.970" /><testcase classname="tests.test_aitenant_lifecycle.TestAITenantLifecycle" name="test_aitenant_create_bootstrap_resources" time="39.600" /><testcase classname="tests.test_aitenant_lifecycle.TestAITenantLifecycle" name="test_aitenant_delete_releases_tenantconfig_finalizer" time="48.385" /><testcase classname="tests.test_aitenant_lifecycle.TestAITenantLifecycle" name="test_aitenant_derives_non_default_tenant_namespace" time="41.917" /><testcase classname="tests.test_api_keys.TestAPIKeyCRUD" name="test_list_api_keys" time="109.681" /><testcase classname="tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_own_keys" time="1.056" /><testcase classname="tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_dry_run" time="1.105" /><testcase classname="tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_dry_run_by_subscription" time="25.404" /><testcase classname="tests.test_api_keys.TestAPIKeyAuthorization" name="test_admin_manage_other_users_keys" time="106.304" /><testcase classname="tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_by_subscription" time="25.089" /><testcase classname="tests.test_api_keys.TestAPIKeyCRUD" name="test_create_api_key" time="135.039" /><testcase classname="tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_other_user_forbidden" time="0.408" /><testcase classname="tests.test_api_keys.TestAPIKeyExpiration" name="test_expiration_policy_boundaries[within-limit]" time="0.274" /><testcase classname="tests.test_api_keys.TestAPIKeyExpiration" name="test_expiration_policy_boundaries[at-limit]" time="0.255" /><testcase classname="tests.test_api_keys.TestAPIKeyExpiration" name="test_expiration_policy_boundaries[exceeds-limit]" time="0.241" /><testcase classname="tests.test_api_keys.TestAPIKeyExpiration" name="test_expiration_policy_boundaries[without-expiration]" time="0.354" /><testcase classname="tests.test_api_keys.TestAPIKeyExpiration" name="test_expiration_policy_boundaries[short-expiration]" time="0.205" /><testcase classname="tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_combined_user_and_subscription" time="25.631" /><testcase classname="tests.test_api_keys.TestAPIKeyModelInference" name="test_api_key_model_access_success" time="0.468" /><testcase classname="tests.test_api_keys.TestAPIKeyModelInference" name="test_no_auth_header_rejected" time="0.045" /><testcase classname="tests.test_api_keys.TestAPIKeyModelInference" name="test_revoked_api_key_rejected" time="3.246" /><testcase classname="tests.test_api_keys.TestAPIKeyModelInference" name="test_api_key_chat_completions" time="0.198" /><testcase classname="tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_double_revoke_returns_404" time="0.460" /><testcase classname="tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_revoke_nonexistent_key_returns_404" time="0.129" /><testcase classname="tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_revoke_then_create_new_key_works" time="0.607" /><testcase classname="tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_individual_revoke_multiple_keys" time="0.796" /><testcase classname="tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_missing_scope_returns_400" time="0.123" /><testcase classname="tests.test_api_keys.TestEphemeralKeyCleanup" name="test_cronjob_exists_and_configured" time="0.142" /><testcase classname="tests.test_api_keys.TestEphemeralKeyCleanup" name="test_cleanup_networkpolicy_exists" time="0.151" /><testcase classname="tests.test_api_keys.TestEphemeralKeyCleanup" name="test_create_ephemeral_key" time="0.484" /><testcase classname="tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_revoke_keys_rejected_at_gateway" time="0.991" /><testcase classname="tests.test_api_keys.TestEphemeralKeyCleanup" name="test_trigger_cleanup_preserves_active_keys" time="0.281"><skipped type="pytest.skip" message="Cannot find maas-api pod in odh-ai-gateway-infra: error: error executing jsonpath &quot;{.items[0].metadata.name}&quot;: Error executing template: array index out of bounds: index 0, length 0. Printing more information for debugging the template:&#10;&#09;template was:&#10;&#09;&#09;{.items[0].metadata.name}&#10;&#09;object given to jsonpath engine was:&#10;&#09;&#09;map[string]interface {}{&quot;apiVersion&quot;:&quot;v1&quot;, &quot;items&quot;:[]interface {}{}, &quot;kind&quot;:&quot;List&quot;, &quot;metadata&quot;:map[string]interface {}{&quot;resourceVersion&quot;:&quot;&quot;}}">/workspace/source/test/e2e/tests/test_api_keys.py:1429: Cannot find maas-api pod in odh-ai-gateway-infra: error: error executing jsonpath "{.items[0].metadata.name}": Error executing template: array index out of bounds: index 0, length 0. Printing more information for debugging the template:
	template was:
		{.items[0].metadata.name}
	object given to jsonpath engine was:
		map[string]interface {}{"apiVersion":"v1", "items":[]interface {}{}, "kind":"List", "metadata":map[string]interface {}{"resourceVersion":""}}</skipped></testcase><testcase classname="tests.test_api_keys.TestAPIKeySubscriptionPhases" name="test_create_key_for_degraded_subscription" time="24.754" /><testcase classname="tests.test_api_keys.TestAPIKeySubscriptionPhases" name="test_create_key_for_active_subscription" time="14.597" /><testcase classname="tests.test_api_keys.TestAPIKeySubscriptionFilter" name="test_search_filters_by_subscription" time="38.943" /><testcase classname="tests.test_api_keys.TestAPIKeyModelInference" name="test_invalid_api_key_rejected" time="0.068" /><testcase classname="tests.test_api_keys.TestAPIKeyLabels" name="test_create_api_key_with_labels" time="0.220" /><testcase classname="tests.test_api_keys.TestAPIKeyLabels" name="test_search_api_keys_by_labels" time="0.508" /><testcase classname="tests.test_api_keys.TestAPIKeyLabels" name="test_labels_validation_errors" time="0.271" /><testcase classname="tests.test_api_keys.TestAPIKeyLabels" name="test_backward_compatibility_no_labels" time="0.502" /><testcase classname="tests.test_authpolicy_generation_stability.TestAuthPolicyGenerationStability" name="test_generation_does_not_increase_during_quiet_window" time="62.446" /><testcase classname="tests.test_api_keys.TestAPIKeyCRUD" name="test_revoke_api_key" time="161.841" /><testcase classname="tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_admin_can_revoke_any_user" time="1.283" /><testcase classname="tests.test_config_tenant.TestConfigAnchorPresence" name="test_cluster_config_default_exists" time="0.555" /><testcase classname="tests.test_api_keys.TestAPIKeySubscriptionPhases" name="test_create_key_for_failed_subscription" time="14.931" /><testcase classname="tests.test_config_tenant.TestConfigAnchorPresence" name="test_cluster_config_not_terminating" time="0.179" /><testcase classname="tests.test_config_tenant.TestConfigTenantOwnership" name="test_tenant_config_lists_config_owner_reference" time="0.154" /><testcase classname="tests.test_config_tenant.TestConfigTenantOwnership" name="test_maas_controller_deployment_does_not_list_config_owner_reference" time="0.152" /><testcase classname="tests.test_config_tenant.TestConfigTenantOwnership" name="test_default_aitenant_lists_config_owner_reference" time="0.505" /><testcase classname="tests.test_external_model_routing.TestPartialWithdrawal" name="test_requests_survive_provider_b_removal" time="0.281"><skipped type="pytest.skip" message="provider withdrawal E2E for #108 is gated; set TENANT_EXTERNAL_MODEL_PARTIAL_WITHDRAWAL_E2E=true to enable (with it set, the #108 contract is expected to hold and a violation fails red)">/workspace/source/test/e2e/tests/test_external_model_routing.py:481: provider withdrawal E2E for #108 is gated; set TENANT_EXTERNAL_MODEL_PARTIAL_WITHDRAWAL_E2E=true to enable (with it set, the #108 contract is expected to hold and a violation fails red)</skipped></testcase><testcase classname="tests.test_external_model_routing.TestLastProviderWithdrawal" name="test_no_route_then_restored_after_recreate" time="0.002"><skipped type="pytest.skip" message="provider withdrawal E2E for #106 is gated; set TENANT_EXTERNAL_MODEL_LAST_PROVIDER_WITHDRAWAL_E2E=true to enable (with it set, the #106 contract is expected to hold and a violation fails red)">/workspace/source/test/e2e/tests/test_external_model_routing.py:564: provider withdrawal E2E for #106 is gated; set TENANT_EXTERNAL_MODEL_LAST_PROVIDER_WITHDRAWAL_E2E=true to enable (with it set, the #106 contract is expected to hold and a violation fails red)</skipped></testcase><testcase classname="tests.test_api_keys.TestAPIKeyAuthorization" name="test_non_admin_cannot_access_other_users_keys" time="173.682" /><testcase classname="tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_by_subscription_forbidden_for_non_admin" time="0.475" /><testcase classname="tests.test_gateway_scoped_authpolicy.TestGatewayAuthPolicyStructure" name="test_gateway_auth_policy_contract" time="10.462" /><testcase classname="tests.test_gateway_scoped_authpolicy.TestGatewayAuthPolicyLifecycle" name="test_gateway_auth_rego_is_fixed_size" time="42.297" /><testcase classname="tests.test_api_keys.TestAPIKeySubscriptionFilter" name="test_search_without_subscription_returns_all" time="1.332" /><testcase classname="tests.test_gateway_scoped_authpolicy.TestGatewayAuthPolicyManagementEndpointAccess" name="test_management_rules_have_model_identity_guards" time="0.168" /><testcase classname="tests.test_gateway_scoped_authpolicy.TestGatewayAuthPolicyManagementEndpointAccess" name="test_gateway_default_auth_scoped_if_present" time="0.001"><skipped type="pytest.skip" message="legacy gateway-default-auth is scoped to the shared default gateway">/workspace/source/test/e2e/tests/test_gateway_scoped_authpolicy.py:212: legacy gateway-default-auth is scoped to the shared default gateway</skipped></testcase><testcase classname="tests.test_model_identity_conflict.TestModelIdentityConflictDetection" name="test_colliding_model_names_flagged_then_resolved" time="80.785" /><testcase classname="tests.test_gateway_filter_chain_praxis.TestGatewayFilterChainPraxis" name="test_no_listener_rejected" time="19.709" /><testcase classname="tests.test_gateway_filter_chain_praxis.TestGatewayFilterChainPraxis" name="test_payload_processing_precedes_router" time="0.001" /><testcase classname="tests.test_external_model_routing.TestProviderSwitching" name="test_switch_a_to_b_to_a_without_extproc_restart" time="99.609" /><testcase classname="tests.test_authpolicy_generation_stability.TestAuthPolicyGenerationStability" name="test_no_rapid_resource_version_changes" time="71.307" /><testcase classname="tests.test_gateway_scoped_authpolicy.TestGatewayAuthPolicyLifecycle" name="test_only_one_gateway_authpolicy_named_maas_gateway_auth" time="0.350" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_deduplication_same_model_multiple_refs" time="142.665" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_user_token_with_subscription_header_filters" time="92.428" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_response_schema_and_metadata" time="10.644" /><testcase classname="tests.test_external_model_routing.TestEqualProviderSelection" name="test_both_providers_receive_traffic" time="99.394" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_invalid_subscription_header_403" time="28.267" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_multiple_distinct_models_in_subscription" time="15.048" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_api_key_ignores_subscription_header" time="34.578" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_access_denied_to_subscription_403" time="33.594" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_empty_subscription_header_value" time="105.458" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_api_key_with_deleted_subscription_403" time="51.809" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_multiple_api_keys_different_subscriptions" time="28.605" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_user_token_returns_all_models" time="177.833" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_service_account_token_multiple_subs_with_header" time="24.850" /><testcase classname="tests.test_multi_tenant_integration.TestMultiTenantIntegration" name="test_full_tenant_lifecycle_create_to_delete" time="391.740" /><testcase classname="tests.test_multi_tenant_integration.TestMultiTenantIntegration" name="test_default_tenant_unaffected_by_multitenancy_enablement" time="18.356" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_api_key_scoped_to_subscription" time="145.984" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_unauthenticated_request_401" time="0.049" /><testcase classname="tests.test_multi_tenant_integration.TestMultiTenantIntegration" name="test_tenant_namespace_label_change_triggers_reconciliation" time="122.566" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_api_key_with_inaccessible_subscription_403" time="13.260" /><testcase classname="tests.test_models_endpoint.TestModelsEndpoint" name="test_service_account_token_multiple_subs_no_header" time="24.397" /><testcase classname="tests.test_multi_tenant_maas_api.TestPerTenantMaaSAPI" name="test_aitenant_creates_dedicated_maas_api_infrastructure" time="93.721" /><testcase classname="tests.test_multi_tenant_maas_api.TestPerTenantMaaSAPI" name="test_tenant_name_environment_variable_set" time="98.638" /><testcase classname="tests.test_namespace_scoping.TestMaaSAPIWatchNamespace" name="test_subscription_in_subscription_namespace_visible_to_api" time="0.000"><skipped type="pytest.skip" message="test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true">/workspace/source/test/e2e/tests/test_namespace_scoping.py:214: test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true</skipped></testcase><testcase classname="tests.test_namespace_scoping.TestMaaSControllerWatchNamespace" name="test_authpolicy_and_subscription_in_maas_subscription_namespace" time="0.000"><skipped type="pytest.skip" message="test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true">/workspace/source/test/e2e/tests/test_namespace_scoping.py:287: test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true</skipped></testcase><testcase classname="tests.test_namespace_scoping.TestMaaSControllerWatchNamespace" name="test_authpolicy_and_subscription_in_another_namespace" time="0.000"><skipped type="pytest.skip" message="test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true">/workspace/source/test/e2e/tests/test_namespace_scoping.py:324: test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true</skipped></testcase><testcase classname="tests.test_namespace_scoping.TestModelRef" name="test_auth_policy_model_ref" time="0.000"><skipped type="pytest.skip" message="test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true">/workspace/source/test/e2e/tests/test_namespace_scoping.py:382: test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true</skipped></testcase><testcase classname="tests.test_namespace_scoping.TestModelRef" name="test_subscription_model_ref" time="0.000"><skipped type="pytest.skip" message="test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true">/workspace/source/test/e2e/tests/test_namespace_scoping.py:456: test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true</skipped></testcase><testcase classname="tests.test_negative_security.TestAPIKeyManagementIsolation" name="test_api_key_cannot_mint_another_api_key" time="38.460" /><testcase classname="tests.test_negative_security.TestHeaderSpoofing" name="test_forged_identity_headers_rejected_on_key_mint[username-only]" time="0.844" /><testcase classname="tests.test_negative_security.TestHeaderSpoofing" name="test_forged_identity_headers_rejected_on_key_mint[keyname-only]" time="0.817" /><testcase classname="tests.test_negative_security.TestHeaderSpoofing" name="test_forged_identity_headers_rejected_on_key_mint[identity-envelope]" time="0.707" /><testcase classname="tests.test_negative_security.TestHeaderSpoofing" name="test_forged_identity_headers_rejected_on_key_mint[admin-scope]" time="0.700" /><testcase classname="tests.test_negative_security.TestHeaderSpoofing" name="test_injected_identity_headers_rejected_on_inference" time="0.405" /><testcase classname="tests.test_negative_security.TestHeaderSpoofing" name="test_duplicate_subscription_headers_ignored" time="8.515" /><testcase classname="tests.test_negative_security.TestExpiredKeyRejection" name="test_expired_key_rejected_at_gateway" time="5.213" /><testcase classname="tests.test_multi_tenant_maas_api.TestPerTenantMaaSAPI" name="test_httproute_tenant_attachment" time="103.727" /><testcase classname="tests.test_multi_tenant_maas_api.TestPerTenantMaaSAPI" name="test_default_and_multiple_tenants_coexist" time="96.196" /><testcase classname="tests.test_negative_security.TestCrossModelAccess" name="test_key_cannot_access_model_outside_subscription" time="0.367" /><testcase classname="tests.test_negative_security.TestMissingModelRef" name="test_authpolicy_with_nonexistent_model_ref" time="120.970"><failure message="TimeoutError: MaaSAuthPolicy e2e-neg-ghost-policy-7a883cd2 did not reach phase 'Degraded' within 120s (last seen: phase=Pending, authPolicies=0 (ready=0))">self = &lt;test_negative_security.TestMissingModelRef object at 0x7f06b0be8850&gt;

    def test_authpolicy_with_nonexistent_model_ref(self):
        """MaaSAuthPolicy does not generate per-model AuthPolicies in gateway-only mode.
    
        Creates an auth policy referencing one valid model and one ghost model,
        waits for Degraded phase, then asserts that no legacy per-model
        AuthPolicies exist for either model.
        """
        suffix = uuid.uuid4().hex[:8]
        policy_name = f"e2e-neg-ghost-policy-{suffix}"
        ghost_model = f"nonexistent-model-{suffix}"
    
        try:
            _create_test_auth_policy(
                policy_name,
                [MODEL_REF, ghost_model],
                groups=["system:authenticated"],
            )
    
&gt;           _wait_for_maas_auth_policy_phase(policy_name, "Degraded", require_auth_policies=False)

test/e2e/tests/test_negative_security.py:578: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

name = 'e2e-neg-ghost-policy-7a883cd2', expected_phase = 'Degraded'
namespace = 'models-as-a-service', timeout = 120, require_auth_policies = False
require_enforced = True

    def _wait_for_maas_auth_policy_phase(name, expected_phase="Active", namespace=None, timeout=AUTHPOLICY_PHASE_TIMEOUT,
                                    require_auth_policies=False, require_enforced=True):
        """Wait for MaaSAuthPolicy to reach a specific phase.
    
        Args:
            name: Name of the MaaSAuthPolicy
            expected_phase: Phase to wait for (default: "Active")
            namespace: Namespace (defaults to _ns())
            timeout: Maximum wait time in seconds (default: 60)
            require_auth_policies: If True, requires authPolicies to be populated (default: False).
                                   Keep False for gateway-only AuthPolicy reconciliation.
            require_enforced: If True (default):
                - with require_auth_policies=True: all status.authPolicies entries must be ready
                - with require_auth_policies=False and expected_phase Active: also wait for the
                  gateway Kuadrant AuthPolicy (maas-gateway-auth) to be Accepted+Enforced
    
        Returns:
            The auth policy CR dict when the expected phase is reached
    
        Raises:
            TimeoutError: If MaaSAuthPolicy doesn't reach expected phase within timeout
        """
        namespace = namespace or _ns()
        deadline = time.time() + timeout
        log.info(f"Waiting for MaaSAuthPolicy {name} to reach phase '{expected_phase}' (timeout: {timeout}s)...")
        last_snapshot = "not found"
    
        while time.time() &lt; deadline:
            cr = _get_cr("maasauthpolicy", name, namespace)
            if cr is None:
                last_snapshot = "not found"
            else:
                status = cr.get("status", {})
                phase = status.get("phase")
                auth_policies = status.get("authPolicies", [])
                ready_count = sum(1 for ap in auth_policies if ap.get("ready") is True)
                last_snapshot = f"phase={phase}, authPolicies={len(auth_policies)} (ready={ready_count})"
    
                if phase == expected_phase:
                    # No per-model auth policies required — phase match is sufficient for the CR,
                    # but gateway-only mode still needs Kuadrant Enforced before HTTP calls.
                    # Callers that intentionally stop Kuadrant (e.g. TRLP degraded tests) must
                    # pass require_enforced=False — Enforced cannot become True while Kuadrant is down.
                    if not require_auth_policies:
                        if require_enforced and expected_phase == "Active":
                            # Keep a floor so a slow phase wait does not starve Kuadrant Enforced.
                            # AuthConfig backlog after policy churn often needs the full enforced timeout.
                            remaining = max(GATEWAY_ENFORCED_TIMEOUT, int(deadline - time.time()))
                            _wait_for_gateway_auth_enforced(timeout=remaining)
                        log.info(f"MaaSAuthPolicy {name} reached phase '{expected_phase}'")
                        return cr
    
                    # Auth policies required — check they exist
                    if len(auth_policies) &gt; 0:
                        if require_enforced:
                            all_enforced = all(
                                ap.get("ready") is True
                                for ap in auth_policies
                            )
                            if all_enforced:
                                log.info(f"MaaSAuthPolicy {name} reached phase '{expected_phase}' and all enforced")
                                return cr
                        else:
                            log.info(f"MaaSAuthPolicy {name} reached phase '{expected_phase}' with {len(auth_policies)} auth policy status(es)")
                            return cr
    
                log.debug(f"MaaSAuthPolicy {name}: {last_snapshot}")
            time.sleep(2)
    
        # Report what the loop last saw: a re-read after the deadline can show a
        # state the loop never evaluated.
&gt;       raise TimeoutError(
            f"MaaSAuthPolicy {name} did not reach phase '{expected_phase}' within {timeout}s "
            f"(last seen: {last_snapshot})"
        )
E       TimeoutError: MaaSAuthPolicy e2e-neg-ghost-policy-7a883cd2 did not reach phase 'Degraded' within 120s (last seen: phase=Pending, authPolicies=0 (ready=0))

test/e2e/tests/test_helper.py:1920: TimeoutError</failure></testcase><testcase classname="tests.test_namespace_scoping.TestMaaSAPIWatchNamespace" name="test_subscription_in_another_namespace_not_visible_to_api" time="0.000"><skipped type="pytest.skip" message="test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true">/workspace/source/test/e2e/tests/test_namespace_scoping.py:247: test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true</skipped></testcase><testcase classname="tests.test_negative_security.TestInternalEndpointIsolation" name="test_internal_endpoint_not_routable[subscriptions-select]" time="0.187" /><testcase classname="tests.test_negative_security.TestInternalEndpointIsolation" name="test_internal_endpoint_not_routable[api-keys-cleanup]" time="0.186" /><testcase classname="tests.test_negative_security.TestInternalEndpointIsolation" name="test_internal_endpoint_not_routable[api-keys-validate]" time="0.194" /><testcase classname="tests.test_negative_security.TestInternalEndpointIsolation" name="test_health_endpoint_accessible" time="0.024" /><testcase classname="tests.test_negative_security.TestInternalEndpointIsolation" name="test_v1_models_via_maas_api_prefix" time="0.272" /><testcase classname="tests.test_networkpolicy.TestPayloadProcessingNetworkPolicyExists" name="test_networkpolicy_exists" time="0.131" /><testcase classname="tests.test_networkpolicy.TestPayloadProcessingNetworkPolicyExists" name="test_pod_selector_covers_both_processors" time="0.134" /><testcase classname="tests.test_networkpolicy.TestPayloadProcessingNetworkPolicyExists" name="test_ingress_uses_istio_managed_label" time="0.145" /><testcase classname="tests.test_networkpolicy.TestPayloadProcessingNetworkPolicyExists" name="test_egress_allows_otlp_to_monitoring_namespace" time="0.274"><skipped type="pytest.skip" message="AIGC praxis NetworkPolicy does not include OTLP 4317 egress (MaaS Go IPP bundle only)">/workspace/source/test/e2e/tests/test_networkpolicy.py:119: AIGC praxis NetworkPolicy does not include OTLP 4317 egress (MaaS Go IPP bundle only)</skipped></testcase><testcase classname="tests.test_networkpolicy.TestPayloadProcessingNetworkPolicyExists" name="test_ingress_does_not_hardcode_single_gateway" time="0.146" /><testcase classname="tests.test_networkpolicy.TestMaaSAuthorinoNetworkPolicy" name="test_rhcl_authorino_namespace_is_allowed" time="0.147" /><testcase classname="tests.test_networkpolicy.TestPayloadProcessingConnectivity" name="test_maas_gateway_pod_exists" time="0.190" /><testcase classname="tests.test_networkpolicy.TestPayloadProcessingConnectivity" name="test_maas_gateway_has_istio_managed_label" time="0.200" /><testcase classname="tests.test_networkpolicy.TestPayloadProcessingConnectivity" name="test_payload_processing_pods_running" time="0.179" /><testcase classname="tests.test_networkpolicy.TestMaaSGatewayFunctional" name="test_maas_api_health" time="0.037" /><testcase classname="tests.test_networkpolicy.TestMaaSGatewayFunctional" name="test_maas_api_models_reachable" time="0.103" /><testcase classname="tests.test_multi_tenant_maas_api.TestPerTenantMaaSAPI" name="test_service_routing_isolation" time="206.247" /><testcase classname="tests.test_negative_security.TestMissingModelRef" name="test_subscription_with_nonexistent_model_ref" time="13.717" /><testcase classname="tests.test_negative_security.TestHeaderAbuse" name="test_special_characters_in_subscription_header" time="15.805" /><testcase classname="tests.test_per_tenant_ipp_isolation.TestPerTenantIPPInfrastructure" name="test_default_tenant_keeps_legacy_ipp_names" time="0.311" /><testcase classname="tests.test_negative_security.TestHeaderSpoofing" name="test_forged_identity_headers_rejected_on_key_mint[group-only]" time="0.665" /><testcase classname="tests.test_per_tenant_ipp_isolation.TestPerTenantIPPInfrastructure" name="test_per_tenant_ipp_deployments_exist" time="170.238" /><testcase classname="tests.test_per_tenant_ipp_isolation.TestPerTenantIPPInfrastructure" name="test_per_tenant_ipp_env_vars" time="0.285"><skipped type="pytest.skip" message="praxis-extproc; Go IPP GATEWAY_NAME/TENANT_NAMESPACE env not applicable">/workspace/source/test/e2e/tests/test_per_tenant_ipp_isolation.py:231: praxis-extproc; Go IPP GATEWAY_NAME/TENANT_NAMESPACE env not applicable</skipped></testcase><testcase classname="tests.test_per_tenant_ipp_isolation.TestPerTenantIPPCleanup" name="test_ipp_resources_removed_on_aitenant_delete" time="67.219" /><testcase classname="tests.test_multi_tenant_integration.TestMultiTenantIntegration" name="test_same_named_resources_across_tenants" time="211.774" /><testcase classname="tests.test_per_tenant_ipp_isolation.TestPerTenantIPPInfrastructure" name="test_multiple_tenant_ipp_stacks_coexist" time="146.186"><failure message="AssertionError: missing IPP deployment payload-processing-e2e-ipp-b-e74c27&#10;assert None is not None">self = &lt;test_per_tenant_ipp_isolation.TestPerTenantIPPInfrastructure object at 0x7f06b0c16b10&gt;
ipp_tenant_cases = ({'suffix': 'f1222e', 'tenant_ns': 'ai-tenant-e2e-ipp-a-f1222e', 'tenant_label_name': 'e2e-ipp-a-f1222e', 'gateway_nam...t_ns': 'ai-tenant-e2e-ipp-b-e74c27', 'tenant_label_name': 'e2e-ipp-b-e74c27', 'gateway_name': 'e2e-ipp-b-e74c27', ...})

    def test_multiple_tenant_ipp_stacks_coexist(self, ipp_tenant_cases):
        deployment_names = {
            per_tenant_ipp_names(case["tenant_label_name"])["processing_deployment"]
            for case in ipp_tenant_cases
        }
        deployment_names.add("payload-processing")
        assert len(deployment_names) == len(ipp_tenant_cases) + 1
        for name in deployment_names:
            deployment = get_json_or_none("deployment", name, GATEWAY_NAMESPACE)
&gt;           assert deployment is not None, f"missing IPP deployment {name}"
E           AssertionError: missing IPP deployment payload-processing-e2e-ipp-b-e74c27
E           assert None is not None

test/e2e/tests/test_per_tenant_ipp_isolation.py:300: AssertionError</failure></testcase><testcase classname="tests.test_per_tenant_ipp_isolation.TestPerTenantIPPInfrastructure" name="test_per_tenant_networkpolicy_when_applied" time="75.693"><skipped type="pytest.skip" message="Per-tenant NetworkPolicy payload-processing-e2e-ipp-b-e74c27 not present (may be blocked by managed-ingress webhook on OpenShift)">/workspace/source/test/e2e/tests/test_per_tenant_ipp_isolation.py:308: Per-tenant NetworkPolicy payload-processing-e2e-ipp-b-e74c27 not present (may be blocked by managed-ingress webhook on OpenShift)</skipped></testcase><testcase classname="tests.test_per_tenant_ipp_isolation.TestPerTenantIPPInfrastructure" name="test_per_tenant_envoyfilter_workload_selector_isolated" time="185.201" /><testcase classname="tests.test_per_tenant_ipp_isolation.TestPerTenantIPPInfrastructure" name="test_per_tenant_envoyfilter_grpc_clusters" time="63.713"><skipped type="pytest.skip" message="praxis-extproc; EnvoyFilter uses payload-*-extproc clusters (see test_per_tenant_praxis_isolation)">/workspace/source/test/e2e/tests/test_per_tenant_ipp_isolation.py:262: praxis-extproc; EnvoyFilter uses payload-*-extproc clusters (see test_per_tenant_praxis_isolation)</skipped></testcase><testcase classname="tests.test_per_tenant_praxis_isolation.TestPerTenantPraxisInfrastructure" name="test_default_tenant_keeps_unsuffixed_payload_processing_names" time="1.169" /><testcase classname="tests.test_per_tenant_ipp_isolation.TestPerTenantIPPRouting" name="test_default_gateway_hits_default_ipp_only" time="314.443" /><testcase classname="tests.test_per_tenant_praxis_isolation.TestPerTenantPraxisInfrastructure" name="test_per_tenant_praxis_deployments_exist" time="116.238" /><testcase classname="tests.test_per_tenant_praxis_isolation.TestPerTenantPraxisInfrastructure" name="test_per_tenant_envoyfilter_grpc_clusters" time="0.307" /><testcase classname="tests.test_per_tenant_praxis_isolation.TestPerTenantPraxisCleanup" name="test_praxis_resources_removed_on_aitenant_delete" time="82.692" /><testcase classname="tests.test_smoke" name="test_healthz_or_404" time="0.064" /><testcase classname="tests.test_smoke" name="test_models_catalog" time="0.223" /><testcase classname="tests.test_smoke" name="test_chat_completions_gateway_alive" time="0.203" /><testcase classname="tests.test_smoke" name="test_chat_completions_streaming_sse" time="0.089" /><testcase classname="tests.test_smoke" name="test_legacy_completions_optionally" time="0.089" /><testcase classname="tests.test_subscription.TestAuthEnforcement" name="test_authorized_user_gets_200" time="0.217" /><testcase classname="tests.test_subscription.TestAuthEnforcement" name="test_no_auth_gets_401" time="0.045" /><testcase classname="tests.test_subscription.TestAuthEnforcement" name="test_invalid_token_gets_403" time="0.163" /><testcase classname="tests.test_subscription.TestAuthEnforcement" name="test_wrong_group_gets_403" time="0.057" /><testcase classname="tests.test_subscription.TestAPIKeySubscriptionBinding" name="test_create_api_key_uses_highest_priority_subscription" time="2.846" /><testcase classname="tests.test_subscription.TestAPIKeySubscriptionBinding" name="test_create_api_key_with_explicit_simulator_subscription" time="0.211" /><testcase classname="tests.test_subscription.TestAPIKeySubscriptionBinding" name="test_create_api_key_nonexistent_subscription_errors" time="18.408" /><testcase classname="tests.test_per_tenant_praxis_isolation.TestPerTenantPraxisInfrastructure" name="test_multiple_tenant_praxis_stacks_coexist" time="123.978" /><testcase classname="tests.test_per_tenant_praxis_isolation.TestPerTenantPraxisInfrastructure" name="test_per_tenant_networkpolicy_when_applied" time="79.655" /><testcase classname="tests.test_per_tenant_praxis_isolation.TestPerTenantPraxisRouting" name="test_default_gateway_hits_default_praxis_only" time="133.681" /><testcase classname="tests.test_subscription.TestSubscriptionEnforcement" name="test_subscribed_user_gets_200" time="0.288" /><testcase classname="tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_multiple_subscriptions_separate_keys_gets_200" time="0.143"><error message="failed on setup with &quot;Failed: PREREQUISITE INVALID: MaaSModelRef 'simulator-w2-105228' not Ready (phase=Unhealthy, endpoint=none). Wait for reconciliation or check controller logs.&quot;">cls = &lt;class 'test_subscription.TestE2ESubscriptionFlow'&gt;

    @classmethod
    def setup_class(cls):
        """Validate test environment prerequisites before running any tests.
    
        This validates that expected resources exist and are in the correct state.
        Tests will FAIL (not skip) if prerequisites are missing, ensuring CI catches issues.
        """
        log.info("=" * 60)
        log.info("Validating E2E Test Prerequisites")
        log.info("=" * 60)
    
        # Validate MODEL_REF exists and is Ready
        model = _get_cr("maasmodelref", MODEL_REF, MODEL_NAMESPACE)
        if not model:
            pytest.fail(f"PREREQUISITE MISSING: MaaSModelRef '{MODEL_REF}' not found. "
                       f"Ensure prow setup has created the model.")
    
        phase = model.get("status", {}).get("phase")
        endpoint = model.get("status", {}).get("endpoint")
        if phase != "Ready" or not endpoint:
&gt;           pytest.fail(f"PREREQUISITE INVALID: MaaSModelRef '{MODEL_REF}' not Ready "
                       f"(phase={phase}, endpoint={endpoint or 'none'}). "
                       f"Wait for reconciliation or check controller logs.")
E           Failed: PREREQUISITE INVALID: MaaSModelRef 'simulator-w2-105228' not Ready (phase=Unhealthy, endpoint=none). Wait for reconciliation or check controller logs.

test/e2e/tests/test_subscription.py:1981: Failed</error></testcase><testcase classname="tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_mint_api_key_denied_for_inaccessible_subscription" time="0.001"><error message="failed on setup with &quot;Failed: PREREQUISITE INVALID: MaaSModelRef 'simulator-w2-105228' not Ready (phase=Unhealthy, endpoint=none). Wait for reconciliation or check controller logs.&quot;">cls = &lt;class 'test_subscription.TestE2ESubscriptionFlow'&gt;

    @classmethod
    def setup_class(cls):
        """Validate test environment prerequisites before running any tests.
    
        This validates that expected resources exist and are in the correct state.
        Tests will FAIL (not skip) if prerequisites are missing, ensuring CI catches issues.
        """
        log.info("=" * 60)
        log.info("Validating E2E Test Prerequisites")
        log.info("=" * 60)
    
        # Validate MODEL_REF exists and is Ready
        model = _get_cr("maasmodelref", MODEL_REF, MODEL_NAMESPACE)
        if not model:
            pytest.fail(f"PREREQUISITE MISSING: MaaSModelRef '{MODEL_REF}' not found. "
                       f"Ensure prow setup has created the model.")
    
        phase = model.get("status", {}).get("phase")
        endpoint = model.get("status", {}).get("endpoint")
        if phase != "Ready" or not endpoint:
&gt;           pytest.fail(f"PREREQUISITE INVALID: MaaSModelRef '{MODEL_REF}' not Ready "
                       f"(phase={phase}, endpoint={endpoint or 'none'}). "
                       f"Wait for reconciliation or check controller logs.")
E           Failed: PREREQUISITE INVALID: MaaSModelRef 'simulator-w2-105228' not Ready (phase=Unhealthy, endpoint=none). Wait for reconciliation or check controller logs.

test/e2e/tests/test_subscription.py:1981: Failed</error></testcase><testcase classname="tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_group_based_access_gets_200" time="0.000"><error message="failed on setup with &quot;Failed: PREREQUISITE INVALID: MaaSModelRef 'simulator-w2-105228' not Ready (phase=Unhealthy, endpoint=none). Wait for reconciliation or check controller logs.&quot;">cls = &lt;class 'test_subscription.TestE2ESubscriptionFlow'&gt;

    @classmethod
    def setup_class(cls):
        """Validate test environment prerequisites before running any tests.
    
        This validates that expected resources exist and are in the correct state.
        Tests will FAIL (not skip) if prerequisites are missing, ensuring CI catches issues.
        """
        log.info("=" * 60)
        log.info("Validating E2E Test Prerequisites")
        log.info("=" * 60)
    
        # Validate MODEL_REF exists and is Ready
        model = _get_cr("maasmodelref", MODEL_REF, MODEL_NAMESPACE)
        if not model:
            pytest.fail(f"PREREQUISITE MISSING: MaaSModelRef '{MODEL_REF}' not found. "
                       f"Ensure prow setup has created the model.")
    
        phase = model.get("status", {}).get("phase")
        endpoint = model.get("status", {}).get("endpoint")
        if phase != "Ready" or not endpoint:
&gt;           pytest.fail(f"PREREQUISITE INVALID: MaaSModelRef '{MODEL_REF}' not Ready "
                       f"(phase={phase}, endpoint={endpoint or 'none'}). "
                       f"Wait for reconciliation or check controller logs.")
E           Failed: PREREQUISITE INVALID: MaaSModelRef 'simulator-w2-105228' not Ready (phase=Unhealthy, endpoint=none). Wait for reconciliation or check controller logs.

test/e2e/tests/test_subscription.py:1981: Failed</error></testcase><testcase classname="tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_group_based_subscription_but_no_auth_gets_403" time="51.846"><error message="failed on setup with &quot;Failed: PREREQUISITE INVALID: MaaSModelRef 'simulator-w2-105228' not Ready (phase=Unhealthy, endpoint=none). Wait for reconciliation or check controller logs.&quot;">cls = &lt;class 'test_subscription.TestE2ESubscriptionFlow'&gt;

    @classmethod
    def setup_class(cls):
        """Validate test environment prerequisites before running any tests.
    
        This validates that expected resources exist and are in the correct state.
        Tests will FAIL (not skip) if prerequisites are missing, ensuring CI catches issues.
        """
        log.info("=" * 60)
        log.info("Validating E2E Test Prerequisites")
        log.info("=" * 60)
    
        # Validate MODEL_REF exists and is Ready
        model = _get_cr("maasmodelref", MODEL_REF, MODEL_NAMESPACE)
        if not model:
            pytest.fail(f"PREREQUISITE MISSING: MaaSModelRef '{MODEL_REF}' not found. "
                       f"Ensure prow setup has created the model.")
    
        phase = model.get("status", {}).get("phase")
        endpoint = model.get("status", {}).get("endpoint")
        if phase != "Ready" or not endpoint:
&gt;           pytest.fail(f"PREREQUISITE INVALID: MaaSModelRef '{MODEL_REF}' not Ready "
                       f"(phase={phase}, endpoint={endpoint or 'none'}). "
                       f"Wait for reconciliation or check controller logs.")
E           Failed: PREREQUISITE INVALID: MaaSModelRef 'simulator-w2-105228' not Ready (phase=Unhealthy, endpoint=none). Wait for reconciliation or check controller logs.

test/e2e/tests/test_subscription.py:1981: Failed</error></testcase><testcase classname="tests.test_per_tenant_praxis_isolation.TestPerTenantPraxisInfrastructure" name="test_per_tenant_envoyfilter_workload_selector_isolated" time="172.872" /><testcase classname="tests.test_subscription.TestOrderingEdgeCases" name="test_subscription_before_auth_policy" time="70.909" /><testcase classname="tests.test_smoke" name="test_tokens_endpoint_replaced_by_api_keys" time="37.447" /><testcase classname="tests.test_per_tenant_ipp_isolation.TestPerTenantIPPRouting" name="test_tenant_gateway_hits_tenant_ipp_only" time="296.487" /><testcase classname="tests.test_per_tenant_praxis_isolation.TestPerTenantPraxisRouting" name="test_tenant_gateway_hits_tenant_praxis_only" time="297.676" /><testcase classname="tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_with_both_access_and_subscription_gets_200" time="51.500" /><testcase classname="tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_with_subscription_but_no_access_gets_403" time="50.535" /></testsuite></testsuites>