use super::{RuleConfigurability, RuleDefaultSeverity, RuleDefinition, RuleLanguage, RuleStatus};
pub(crate) const RULE_DEFINITIONS: &[RuleDefinition] = &[
RuleDefinition {
id: "celery_delay_in_loop_without_canvas",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Celery tasks dispatch .delay(...) or .apply_async(...) inside loops without an obvious canvas primitive such as group() or chord().",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "celery_result_get_inside_task",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Celery tasks synchronously wait on AsyncResult.get(...) instead of handing work off asynchronously.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "celery_task_reads_env_per_invocation",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Celery task bodies repeatedly read environment configuration instead of using startup-time bootstrap.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "click_typer_config_file_loaded_per_command",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "click or typer commands parse config files on each invocation instead of using shared bootstrap or dependency setup.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "click_typer_env_lookup_per_command",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "click or typer commands scatter repeated environment lookups through the command body.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "click_typer_http_client_created_per_command",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "click or typer commands allocate HTTP clients inside command bodies instead of reusing a shared client factory.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "django_all_without_limit_in_view",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Django views call .all() without visible pagination, slicing, or limiting.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "django_create_single_in_loop",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Django code creates one model at a time inside loops instead of using bulk_create().",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "django_delete_single_in_loop",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Django code deletes individual models inside loops instead of using set-based queryset deletion.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "django_migration_code_in_view",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Django views or request paths reference schema or migration operations that belong in migrations.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "django_n_plus_one_no_select_related",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Django queryset iteration shows N+1 risk with no visible select_related(...) or prefetch_related(...).",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "django_queryset_count_then_exists",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Django querysets use count() for existence checks instead of exists().",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "django_queryset_evaluated_multiple_times",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "The same Django queryset appears to be evaluated multiple times in one function.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "django_queryset_len_instead_of_count",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "len(queryset) is used where queryset.count() would avoid loading every row.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "django_queryset_order_by_random",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Django querysets use order_by(\\\"?\\\") or equivalent random ordering on request paths.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "django_raw_sql_in_loop",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Django request or service code executes raw SQL inside loops instead of batching.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "django_save_full_model_in_loop",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Django code saves full model instances in loops without update_fields or bulk updates.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "django_update_single_in_loop",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Django code updates one row at a time inside loops instead of using bulk or set-based updates.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "django_values_vs_full_model_in_loop",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Django loops hydrate full model instances where values(), values_list(), or only() would likely be cheaper.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "fastapi_background_task_exception_silent",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "FastAPI background task dispatches appear to rely on default exception behavior without visible error handling.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "fastapi_dependency_creates_client_per_request",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "FastAPI dependencies construct HTTP clients per request instead of using app lifespan or shared setup.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "fastapi_response_model_without_orm_mode",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "FastAPI response models use ORM conversion paths without visible ORM compatibility configuration.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "fastapi_sync_def_with_blocking_io",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "FastAPI sync route handlers perform blocking I/O instead of using async routes or executor offload.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "flask_app_config_read_per_request",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Flask views repeatedly read app.config on request paths instead of consuming bootstrapped settings.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "flask_debug_mode_in_production_code",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Flask code enables debug=True in application runtime paths.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "flask_file_read_per_request",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Flask views read files directly on request paths instead of using cached or static responses.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "flask_global_db_connection_per_request",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Flask views create database connections per request instead of using pooled or app-scoped access.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "flask_json_encoder_per_request",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Flask views instantiate JSON encoders per request instead of reusing app-level serialization setup.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "flask_no_streaming_for_large_response",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Flask views build large in-memory responses where generator or streaming responses would fit better.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "flask_request_body_parsed_multiple_times",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Flask request handlers parse the same request body multiple times.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "flask_template_rendered_from_string_in_view",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Flask views render templates from inline strings instead of using file-backed templates.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "large_dict_literal_response_in_handler",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Handlers build large inline dict responses where typed response models would be clearer and cheaper.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "middleware_compiles_regex_per_request",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Middleware compiles regex patterns per request instead of precompiling them.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "middleware_creates_http_client_per_request",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Middleware creates HTTP clients per request instead of reusing app-scoped clients.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "middleware_loads_config_file_per_request",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Middleware loads config files on request paths instead of using startup configuration.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "pydantic_model_dump_then_json_dumps",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Pydantic v2 code serializes model_dump() output through json.dumps(...) instead of using model_dump_json().",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "pydantic_model_validate_after_json_loads",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Pydantic v2 validation is preceded by json.loads(...) even though model_validate_json() could validate raw JSON directly.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "response_json_dumps_then_response_object",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Handlers manually json.dumps(...) payloads and then wrap them in framework Response objects.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "sqlalchemy_commit_per_row_in_loop",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "SQLAlchemy sessions commit inside loops instead of batching changes and committing once.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "sqlalchemy_create_engine_per_request",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "SQLAlchemy engines are created on request or handler paths instead of being process-scoped.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "sqlalchemy_expire_on_commit_default_in_async",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Async SQLAlchemy sessions rely on the default expire_on_commit behavior instead of making the async access pattern explicit.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "sqlalchemy_n_plus_one_lazy_load",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "SQLAlchemy query shapes suggest lazy-loaded N+1 access with no visible eager loading.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "sqlalchemy_query_in_loop",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "SQLAlchemy code issues queries inside loops instead of batching or prefetching.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "sqlalchemy_session_not_closed",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "SQLAlchemy Session objects are created without context-manager or close handling.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "sqlmodel_commit_per_row_in_loop",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "SQLModel sessions commit inside loops instead of applying one transaction after batched updates.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "sqlmodel_session_exec_in_loop",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "SQLModel Session.exec(...) is called inside loops instead of combining the query shape.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "sqlmodel_unbounded_select_in_handler",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Handlers execute SQLModel select().all() paths without visible limits or pagination.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "template_render_in_loop",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Template rendering appears inside loops instead of rendering once over prepared data.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "upstream_call_without_timeout_in_handler",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Request handlers issue upstream HTTP calls without visible timeout configuration.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "upstream_http_call_per_item_in_handler",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Request handlers make sequential upstream HTTP calls inside loops instead of batching or bounded concurrency.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
RuleDefinition {
id: "upstream_response_not_checked_before_decode",
language: RuleLanguage::Python,
family: "framework",
default_severity: RuleDefaultSeverity::Contextual,
status: RuleStatus::Stable,
configurability: &[
RuleConfigurability::Disable,
RuleConfigurability::Ignore,
RuleConfigurability::SeverityOverride,
],
description: "Handlers decode upstream responses without visible status checks such as raise_for_status() or status_code guards.",
binding_location: super::bindings::PYTHON_FRAMEWORK,
},
];