Skip to content

Commit c423f4e

Browse files
committed
fix: add required utils and audit docs (db_connection, retry_policies)
- scripts/utils/db_connection.py, retry_policies.py: required by audit_monitor, feedback_tracker, dast_scanner, threat_intel_enricher, supply_chain_analyzer, run_ai_audit - docs: CODE_REVIEW_STILL_LEFT.md, CONFIG_REFERENCE.md, V3_CONTINUOUS_SECURITY_MODULES.md, ADR 0004 - tests: unit tests for agent_chain_discovery, app_context_builder, autofix_pr_generator, findings_store Made-with: Cursor
1 parent c90ca5f commit c423f4e

10 files changed

+778
-0
lines changed

docs/CODE_REVIEW_STILL_LEFT.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Code Review — What’s Still Left
2+
3+
**Date:** March 2026
4+
**Context:** Follow-up to the audit fixes (path traversal, Ruff, test robustness, docs). This document lists **remaining** items: not yet done, or optional improvements.
5+
6+
---
7+
8+
## Already fixed (no action needed)
9+
10+
- **Path traversal in AutoFix**`_apply_fix()` validates `file_path` via `validate_path_safe()`; empty and out-of-project paths rejected.
11+
- **Ruff** — Lint and format applied across `scripts/`.
12+
- **Fixtures doc**`tests/fixtures/README.md`; test_remediation_fixes_apply_cleanly.py docstring states that `subprocess.run(cmd, shell=True)` appears only in fixture/file content and is never executed by the test runner.
13+
- **Production security** — No `shell=True` with user input in production; parameterized SQL; `yaml.safe_load()` in production code.
14+
- **validate_path_safe** — Uses `os.path.commonpath()` for portability (e.g. Windows). advanced_suppression optional `project_root` validation added.
15+
- **Config reference**`docs/CONFIG_REFERENCE.md` lists 47+ config keys and env vars.
16+
- **v3 summary**`docs/V3_CONTINUOUS_SECURITY_MODULES.md` and CLAUDE.md link diff scope, findings store, app context, autofix.
17+
- **ADR v3**`docs/adrs/0004-v3-continuous-security.md`.
18+
- **HybridSecurityAnalyzer** — Scanner/feature loading extracted to `_load_scanners_and_features()`.
19+
- **run_ai_audit**`_run_single_path_audit()` and `_run_multi_agent_audit()` extracted; `run_audit()` delegates to them.
20+
- **Shared SQLite helper**`scripts/utils/db_connection.py`; audit_monitor and feedback_tracker use `with db_connection(...)` throughout.
21+
- **Shared retry policies**`scripts/utils/retry_policies.py`; run_ai_audit, threat_intel_enricher, dast_scanner, supply_chain_analyzer use them.
22+
- **Scanner runner harness**`run_scanner_guarded()` in `scripts/hybrid/scanner_runners.py`; run_semgrep, run_trivy, run_checkov, run_api_security, run_supply_chain, run_fuzzing, run_runtime_security, run_regression_testing, run_dast, run_gitleaks all use it. run_threat_intel and run_remediation are enrichment-style (return original list on exception) and can stay as-is or use a variant harness.
23+
- **Fixture comments** — conftest and test_phase1_integration: short comments/docstrings state that fixture content written to disk is vulnerable-by-design for scanners only and must not be executed with untrusted input.
24+
- **advanced_suppression config_path** — Optional `project_root` validation: when set, `config_path` is validated against project root via `validate_path_safe`; on failure a warning is logged and a safe default is used.
25+
- **Unit tests** — test_autofix_pr_generator.py, test_agent_chain_discovery.py, test_findings_store.py, test_app_context_builder.py added.
26+
27+
---
28+
29+
## 1. Security (optional)
30+
31+
### 1.1 Test and fixture code
32+
33+
- **test_remediation_fixes_apply_cleanly.py** — The `subprocess.run(cmd, shell=True)` occurrences are inside **string literals** (fixture content / file content for scanners). The test runner never executes subprocess with shell=True. Docstring updated; no code change required.
34+
- **conftest / test_phase1** — Done: comments/docstrings added that fixture content written to disk is vulnerable-by-design for scanners only and must not be executed with untrusted input.
35+
- **advanced_suppression** — Done: optional `project_root` validation for `config_path` when set from config.
36+
37+
---
38+
39+
## 2. Architecture and code quality (remaining)
40+
41+
### 2.1 Done
42+
43+
- Scanner loader in hybrid_analyzer (`_load_scanners_and_features`).
44+
- run_audit split (`_run_single_path_audit`, `_run_multi_agent_audit`).
45+
- Shared db_connection and retry_policies.
46+
- Scanner runner harness (`run_scanner_guarded`); run_semgrep, run_trivy, run_checkov, run_api_security, run_supply_chain, run_fuzzing, run_runtime_security, run_regression_testing, run_dast, run_gitleaks all migrated. run_threat_intel and run_remediation are enrichment-style and optionally can use a variant that returns the original list on exception.
47+
48+
### 2.2 Still optional
49+
50+
- **Large-file splits** — run_ai_audit, supply_chain_analyzer, audit_monitor, etc. remain single large files. Splitting by feature/phase is long-term (> 5 days).
51+
- **Enrichment runners** — run_threat_intel and run_remediation could use a guarded variant that returns the original findings list on exception (optional).
52+
53+
---
54+
55+
## 3. Testing
56+
57+
- **autofix_pr_generator**`tests/unit/test_autofix_pr_generator.py` (path validation, mocked git).
58+
- **agent_chain_discovery**`tests/unit/test_agent_chain_discovery.py` (mocked LLM).
59+
- **FindingsStore**`tests/unit/test_findings_store.py` (edge cases: empty scan, get_finding missing, fingerprint).
60+
- **AppContextBuilder**`tests/unit/test_app_context_builder.py` (empty dir, to_prompt_context, nonexistent path).
61+
62+
---
63+
64+
## 4. Summary table
65+
66+
| Category | Done | Still left |
67+
|-----------------------|------|------------|
68+
| **Security (critical)** | Path traversal, path validation, fixture comments, advanced_suppression config_path ||
69+
| **Security (production)** | Subprocess, SQL, YAML OK ||
70+
| **Architecture** | Scanner loader, run_audit split, db_connection, retry_policies, scanner harness | Large-file splits (long-term) |
71+
| **Config / v3 docs** | CONFIG_REFERENCE, v3 summary, ADR 0004 ||
72+
| **Tests** | autofix, agent_chain, FindingsStore, AppContextBuilder ||
73+
| **Maintainability** | ADR v3, shared SQLite, retry policies ||
74+
75+
---
76+
77+
## References
78+
79+
- [CODE_AUDIT_REPORT.md](CODE_AUDIT_REPORT.md) — Full audit and action plan
80+
- [CODE_REVIEW_FINDINGS.md](CODE_REVIEW_FINDINGS.md) — Security-focused review
81+
- [CLAUDE.md](../CLAUDE.md) — Project overview
82+
- [CONFIG_REFERENCE.md](CONFIG_REFERENCE.md) — Config keys and env vars
83+
- [V3_CONTINUOUS_SECURITY_MODULES.md](V3_CONTINUOUS_SECURITY_MODULES.md) — v3 module summary
84+
- [adrs/0004-v3-continuous-security.md](adrs/0004-v3-continuous-security.md) — ADR v3

docs/CONFIG_REFERENCE.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# Config Reference
2+
3+
All configuration keys and their defaults. Override via **profile YAML**, **.argus.yml**, **environment variables**, or **CLI**. Precedence: defaults < profile < .argus.yml < env < CLI.
4+
5+
Source: `scripts/config_loader.get_default_config()` and `_ENV_MAPPINGS`.
6+
7+
---
8+
9+
## AI
10+
11+
| Key | Default | Env var(s) |
12+
|-----|---------|------------|
13+
| ai_provider | auto | AI_PROVIDER, INPUT_AI_PROVIDER |
14+
| model | auto | MODEL, INPUT_MODEL |
15+
| multi_agent_mode | single | MULTI_AGENT_MODE, INPUT_MULTI_AGENT_MODE |
16+
| anthropic_api_key | "" | ANTHROPIC_API_KEY |
17+
| openai_api_key | "" | OPENAI_API_KEY |
18+
| ollama_endpoint | "" | OLLAMA_ENDPOINT |
19+
20+
## Scanners
21+
22+
| Key | Default | Env var(s) |
23+
|-----|---------|------------|
24+
| enable_semgrep | true | ENABLE_SEMGREP, SEMGREP_ENABLED |
25+
| enable_trivy | true | ENABLE_TRIVY |
26+
| enable_checkov | true | ENABLE_CHECKOV |
27+
| enable_api_security | true | ENABLE_API_SECURITY |
28+
| enable_dast | false | ENABLE_DAST |
29+
| enable_supply_chain | true | ENABLE_SUPPLY_CHAIN |
30+
| enable_fuzzing | false | ENABLE_FUZZING |
31+
| enable_threat_intel | true | ENABLE_THREAT_INTEL |
32+
| enable_remediation | true | ENABLE_REMEDIATION |
33+
| enable_runtime_security | false | ENABLE_RUNTIME_SECURITY |
34+
| enable_regression_testing | true | ENABLE_REGRESSION_TESTING |
35+
| enable_gitleaks | true | ENABLE_GITLEAKS |
36+
| enable_nuclei_templates | true | ENABLE_NUCLEI_TEMPLATES |
37+
| enable_zap_baseline | false | ENABLE_ZAP_BASELINE |
38+
39+
## DAST (orchestrator)
40+
41+
| Key | Default | Env var(s) |
42+
|-----|---------|------------|
43+
| dast_target_url | "" | DAST_TARGET_URL |
44+
| dast_auth_config_path | "" | DAST_AUTH_CONFIG_PATH |
45+
| dast_enable_nuclei | true | DAST_ENABLE_NUCLEI |
46+
| dast_enable_zap | true | DAST_ENABLE_ZAP |
47+
| dast_max_duration | 900 | DAST_MAX_DURATION |
48+
| dast_parallel_agents | true | DAST_PARALLEL_AGENTS |
49+
50+
## Feature toggles
51+
52+
| Key | Default | Env var(s) |
53+
|-----|---------|------------|
54+
| enable_multi_agent | true | ENABLE_MULTI_AGENT, INPUT_ENABLE_MULTI_AGENT |
55+
| enable_spontaneous_discovery | true | ENABLE_SPONTANEOUS_DISCOVERY |
56+
| enable_collaborative_reasoning | false | ENABLE_COLLABORATIVE_REASONING |
57+
| enable_ai_enrichment | true | ENABLE_AI_ENRICHMENT |
58+
| enable_threat_modeling | true | ENABLE_THREAT_MODELING |
59+
| enable_sandbox_validation | true | ENABLE_SANDBOX_VALIDATION |
60+
| enable_heuristics | true | ENABLE_HEURISTICS |
61+
| enable_consensus | true | ENABLE_CONSENSUS |
62+
| enable_iris | true | ENABLE_IRIS |
63+
| enable_proof_by_exploitation | false | ENABLE_PROOF_BY_EXPLOITATION |
64+
| max_exploit_attempts | 10 | MAX_EXPLOIT_ATTEMPTS |
65+
| enable_audit_trail | true | ENABLE_AUDIT_TRAIL |
66+
| audit_save_prompts | true | AUDIT_SAVE_PROMPTS |
67+
| enable_smart_retry | true | ENABLE_SMART_RETRY |
68+
| retry_max_attempts | 3 | RETRY_MAX_ATTEMPTS |
69+
| retry_billing_delay | 60 | RETRY_BILLING_DELAY |
70+
71+
## Limits & files
72+
73+
| Key | Default | Env var(s) |
74+
|-----|---------|------------|
75+
| max_files | 50 | MAX_FILES, INPUT_MAX_FILES |
76+
| max_file_size | 50000 | MAX_FILE_SIZE, INPUT_MAX_FILE_SIZE |
77+
| max_tokens | 8000 | MAX_TOKENS, INPUT_MAX_TOKENS |
78+
| cost_limit | 1.0 | COST_LIMIT, INPUT_COST_LIMIT |
79+
| only_changed | false | ONLY_CHANGED, INPUT_ONLY_CHANGED |
80+
| include_paths | "" | INCLUDE_PATHS, INPUT_INCLUDE_PATHS |
81+
| exclude_paths | .github/**,node_modules/**,... | EXCLUDE_PATHS, INPUT_EXCLUDE_PATHS |
82+
83+
## Deep analysis
84+
85+
| Key | Default | Env var(s) |
86+
|-----|---------|------------|
87+
| deep_analysis_mode | off | DEEP_ANALYSIS_MODE |
88+
| deep_analysis_max_files | 50 | DEEP_ANALYSIS_MAX_FILES, MAX_FILES_DEEP_ANALYSIS |
89+
| deep_analysis_timeout | 300 | DEEP_ANALYSIS_TIMEOUT |
90+
| deep_analysis_cost_ceiling | 5.0 | DEEP_ANALYSIS_COST_CEILING |
91+
92+
## Phase gating & parallel
93+
94+
| Key | Default | Env var(s) |
95+
|-----|---------|------------|
96+
| enable_phase_gating | true | ENABLE_PHASE_GATING |
97+
| phase_gate_strict | false | PHASE_GATE_STRICT |
98+
| enable_parallel_agents | true | ENABLE_PARALLEL_AGENTS |
99+
| parallel_agent_workers | 3 | PARALLEL_AGENT_WORKERS |
100+
101+
## Vulnerability enrichment & compliance
102+
103+
| Key | Default | Env var(s) |
104+
|-----|---------|------------|
105+
| enable_license_risk_scoring | true | ENABLE_LICENSE_RISK_SCORING |
106+
| enable_epss_scoring | true | ENABLE_EPSS_SCORING |
107+
| epss_cache_ttl_hours | 24 | EPSS_CACHE_TTL_HOURS |
108+
| enable_fix_version_tracking | true | ENABLE_FIX_VERSION_TRACKING |
109+
| enable_vex | true | ENABLE_VEX |
110+
| vex_paths | "" | VEX_PATHS |
111+
| vex_auto_discover_dir | .argus/vex | VEX_AUTO_DISCOVER_DIR |
112+
| enable_vuln_deduplication | true | ENABLE_VULN_DEDUPLICATION |
113+
| deduplication_strategy | auto | DEDUPLICATION_STRATEGY |
114+
| enable_advanced_suppression | true | ENABLE_ADVANCED_SUPPRESSION |
115+
| suppression_auto_expire_days | 90 | SUPPRESSION_AUTO_EXPIRE_DAYS |
116+
| enable_compliance_mapping | true | ENABLE_COMPLIANCE_MAPPING |
117+
| compliance_frameworks | "" | COMPLIANCE_FRAMEWORKS |
118+
119+
## Continuous security (v3)
120+
121+
| Key | Default | Env var(s) |
122+
|-----|---------|------------|
123+
| enable_diff_scoping | true | ENABLE_DIFF_SCOPING |
124+
| diff_expand_impact_radius | true | DIFF_EXPAND_IMPACT_RADIUS |
125+
| enable_autofix_pr | false | ENABLE_AUTOFIX_PR |
126+
| autofix_confidence_threshold | high | AUTOFIX_CONFIDENCE_THRESHOLD |
127+
| autofix_max_prs_per_scan | 5 | AUTOFIX_MAX_PRS_PER_SCAN |
128+
| enable_findings_store | true | ENABLE_FINDINGS_STORE |
129+
| findings_db_path | .argus/findings.db | FINDINGS_DB_PATH |
130+
| inject_historical_context | true | INJECT_HISTORICAL_CONTEXT |
131+
| enable_agent_chain_discovery | false | ENABLE_AGENT_CHAIN_DISCOVERY |
132+
| enable_cross_component_analysis | true | ENABLE_CROSS_COMPONENT_ANALYSIS |
133+
| enable_app_context | true | ENABLE_APP_CONTEXT |
134+
| enable_live_validation | false | ENABLE_LIVE_VALIDATION |
135+
| live_validation_environment | staging | LIVE_VALIDATION_ENVIRONMENT |
136+
137+
## Other
138+
139+
| Key | Default | Env var(s) |
140+
|-----|---------|------------|
141+
| enable_mcp_server | false | ENABLE_MCP_SERVER |
142+
| enable_quality_filter | true | ENABLE_QUALITY_FILTER |
143+
| quality_filter_min_confidence | 0.30 | QUALITY_FILTER_MIN_CONFIDENCE |
144+
| review_type | audit ||
145+
| project_type | auto ||
146+
| fail_on | "" | FAIL_ON, INPUT_FAIL_ON |
147+
| agent_profile | default ||
148+
| enable_temporal | false | ENABLE_TEMPORAL |
149+
| temporal_server | localhost:7233 | TEMPORAL_SERVER |
150+
| temporal_namespace | argus | TEMPORAL_NAMESPACE |
151+
| temporal_retry_mode | production | TEMPORAL_RETRY_MODE |
152+
| consensus_threshold | 0.5 | CONSENSUS_THRESHOLD |
153+
| exploitability_threshold | moderate | EXPLOITABILITY_THRESHOLD |
154+
| fuzzing_duration | 300 | FUZZING_DURATION |
155+
| runtime_monitoring_duration | 60 | RUNTIME_MONITORING_DURATION |
156+
157+
For full env-to-key mapping and types, see `config_loader._ENV_MAPPINGS` and `build_unified_config()`.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Continuous Security (v3) — Module Summary
2+
3+
One-place overview of v3 modules. For full architecture, see [CONTINUOUS_SECURITY_TESTING_GUIDE.md](CONTINUOUS_SECURITY_TESTING_GUIDE.md).
4+
5+
---
6+
7+
## Modules
8+
9+
| Module | Script | Config toggles | Purpose |
10+
|--------|--------|----------------|---------|
11+
| **Diff-intelligent scoping** | `scripts/diff_impact_analyzer.py` | enable_diff_scoping, diff_expand_impact_radius | Scope scanners to changed files; expand blast radius (e.g. if auth middleware changed, scan all files that import it). |
12+
| **Persistent findings store** | `scripts/findings_store.py` | enable_findings_store, findings_db_path, inject_historical_context | SQLite-backed cross-scan store; regression detection; historical context into LLM prompts. |
13+
| **Application context** | `scripts/app_context_builder.py` | enable_app_context | Detect framework, auth, cloud, IaC; generate context string for LLM. |
14+
| **AutoFix PR generation** | `scripts/autofix_pr_generator.py` | enable_autofix_pr, autofix_confidence_threshold, autofix_max_prs_per_scan | Generate branches/PRs from remediation suggestions; path-validated file writes. |
15+
| **Agent chain discovery** | `scripts/agent_chain_discovery.py` | enable_agent_chain_discovery | LLM-powered multi-step attack chain discovery. |
16+
| **Cross-component analysis** | (in agent_chain_discovery) | enable_cross_component_analysis | Detect dangerous finding combinations across boundaries. |
17+
| **SAST-to-DAST validation** | `scripts/sast_dast_validator.py` | enable_live_validation, live_validation_environment | Validate SAST findings against live (staging) targets. |
18+
19+
---
20+
21+
## Quick links
22+
23+
- [CONTINUOUS_SECURITY_TESTING_GUIDE.md](CONTINUOUS_SECURITY_TESTING_GUIDE.md) — Architecture and gap analysis
24+
- [ADR-0004](adrs/0004-v3-continuous-security.md) — Decisions and trade-offs
25+
- [.claude/rules/features.md](../.claude/rules/features.md) — Feature toggles and config keys
26+
- [CONFIG_REFERENCE.md](CONFIG_REFERENCE.md) — All config keys and env vars
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
title: ADR-0004 - v3 Continuous Security (Findings Store, Diff Scoping, App Context, AutoFix)
3+
status: Accepted
4+
date: 2026-03
5+
---
6+
7+
# ADR-0004: v3 Continuous Security
8+
9+
## Status
10+
11+
**Accepted** | Date: 2026-03
12+
13+
## Context
14+
15+
Post–Phase 6 we need:
16+
17+
- **Cross-scan intelligence** — Know what was fixed, what regressed, and feed history into triage.
18+
- **Efficient rescans** — Scope to changed code and blast radius instead of full repo every time.
19+
- **Context-aware triage** — LLM should know framework, auth, and deployment context.
20+
- **Closed-loop remediation** — Generate fix branches/PRs from suggestions with safety (path validation, no arbitrary writes).
21+
22+
## Decision
23+
24+
Introduce **v3 continuous security** modules, all opt-in or default-on with safe defaults:
25+
26+
1. **Persistent findings store** — SQLite at `.argus/findings.db`; content-based fingerprinting; regression detection; optional historical context injection into Phase 2 prompts. Toggle: `enable_findings_store`, `inject_historical_context`.
27+
2. **Diff-intelligent scoping** — Classify changed files by security relevance; expand to dependents (e.g. callers of changed auth). Drive Semgrep/scan include paths. Toggles: `enable_diff_scoping`, `diff_expand_impact_radius`.
28+
3. **Application context builder** — Detect framework, auth, cloud, IaC; produce a context string for LLM. Toggle: `enable_app_context`.
29+
4. **AutoFix PR generator** — Create branches and apply fixes from remediation suggestions; **path validation** so `file_path` never escapes project root. Toggles: `enable_autofix_pr`, `autofix_confidence_threshold`, `autofix_max_prs_per_scan`.
30+
5. **Agent chain discovery** — LLM-powered attack chain discovery. Toggle: `enable_agent_chain_discovery` (opt-in, uses credits).
31+
6. **SAST-to-DAST live validation** — Optional validation against staging; never production by default. Toggles: `enable_live_validation`, `live_validation_environment`.
32+
33+
## Consequences
34+
35+
- **Positive:** Regression visibility, faster rescans, better triage, safe autofix, optional live validation.
36+
- **Operational:** SQLite and `.argus/` directory; config surface increases (see CONFIG_REFERENCE).
37+
- **Security:** Path validation in AutoFix and optional `project_root` in advanced_suppression; no execution of user-controlled paths without validation.
38+
39+
## References
40+
41+
- [CONTINUOUS_SECURITY_TESTING_GUIDE.md](../CONTINUOUS_SECURITY_TESTING_GUIDE.md)
42+
- [V3_CONTINUOUS_SECURITY_MODULES.md](../V3_CONTINUOUS_SECURITY_MODULES.md)
43+
- [CONFIG_REFERENCE.md](../CONFIG_REFERENCE.md)

scripts/utils/db_connection.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""
2+
Shared SQLite connection helper for audit_monitor and feedback_tracker.
3+
Provides a context manager that opens a connection, yields (conn, cursor), commits on success, and closes.
4+
"""
5+
6+
import sqlite3
7+
from contextlib import contextmanager
8+
from pathlib import Path
9+
from typing import Iterator
10+
11+
12+
@contextmanager
13+
def db_connection(db_path: str | Path) -> Iterator[tuple[sqlite3.Connection, sqlite3.Cursor]]:
14+
"""
15+
Context manager for SQLite: connect, yield (conn, cursor), commit, then close.
16+
17+
Usage:
18+
with db_connection(self.db_path) as (conn, cursor):
19+
cursor.execute(...)
20+
"""
21+
conn = sqlite3.connect(str(db_path))
22+
try:
23+
cursor = conn.cursor()
24+
yield conn, cursor
25+
conn.commit()
26+
finally:
27+
conn.close()

scripts/utils/retry_policies.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""
2+
Shared tenacity retry policies for LLM, HTTP, and subprocess calls.
3+
Use these instead of defining retry logic inline for consistency and maintainability.
4+
"""
5+
6+
import json
7+
import subprocess
8+
from tenacity import (
9+
retry_if_exception_type,
10+
stop_after_attempt,
11+
wait_exponential,
12+
)
13+
14+
# ---------------------------------------------------------------------------
15+
# LLM / API (Connection, Timeout)
16+
# ---------------------------------------------------------------------------
17+
18+
LLM_RETRY_EXCEPTIONS = (ConnectionError, TimeoutError)
19+
LLM_STOP = stop_after_attempt(3)
20+
LLM_WAIT = wait_exponential(multiplier=1, min=4, max=10)
21+
LLM_RETRY = retry_if_exception_type(LLM_RETRY_EXCEPTIONS)
22+
23+
# ---------------------------------------------------------------------------
24+
# HTTP / URL (URLError, HTTPError, ConnectionError, TimeoutError)
25+
# ---------------------------------------------------------------------------
26+
27+
def get_http_retry_exceptions():
28+
import urllib.error
29+
return (urllib.error.URLError, urllib.error.HTTPError, ConnectionError, TimeoutError)
30+
31+
HTTP_STOP = stop_after_attempt(3)
32+
HTTP_WAIT = wait_exponential(multiplier=1, min=2, max=60)
33+
34+
def http_retry_if():
35+
return retry_if_exception_type(get_http_retry_exceptions())
36+
37+
# ---------------------------------------------------------------------------
38+
# Subprocess (SubprocessError, OSError, RuntimeError)
39+
# ---------------------------------------------------------------------------
40+
41+
SUBPROCESS_RETRY_EXCEPTIONS = (subprocess.SubprocessError, OSError, RuntimeError)
42+
SUBPROCESS_STOP = stop_after_attempt(3)
43+
SUBPROCESS_WAIT = wait_exponential(multiplier=1, min=2, max=60)
44+
SUBPROCESS_RETRY = retry_if_exception_type(SUBPROCESS_RETRY_EXCEPTIONS)
45+
46+
# Subprocess + JSON decode (e.g. supply chain scorecard)
47+
SUBPROCESS_JSON_RETRY = retry_if_exception_type(
48+
(subprocess.SubprocessError, OSError, RuntimeError, json.JSONDecodeError)
49+
)

0 commit comments

Comments
 (0)