-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathpyproject.toml
More file actions
285 lines (257 loc) · 9.81 KB
/
Copy pathpyproject.toml
File metadata and controls
285 lines (257 loc) · 9.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
[project]
name = "cybernetic-governance-engine"
version = "3.0.0"
description = "CAGE — Cybernetic AI Governance Engine"
authors = [{ name = "OSS Maintainer", email = "oss-maintainer@example.com" }]
license = "Apache-2.0"
readme = "README.md"
dependencies = [
# Core: truly universal deps used across all services
"pydantic>=2.10.6",
"python-dotenv>=1.0.1",
"httpx>=0.27.0",
"python-json-logger>=2.0.7",
"cachetools>=5.5.0",
"nest-asyncio>=1.6.0",
"networkx>=3.3",
"redis>=5.0.0",
"litellm>=1.0.0",
# Core OTEL — shared across gateway, advisor, compliance
"opentelemetry-api>=1.38.0",
"opentelemetry-sdk>=1.38.0",
"opentelemetry-exporter-otlp>=1.38.0",
"opentelemetry-semantic-conventions-ai>=0.4.0",
# HTTP serving — used by gateway AND compliance_bridge
"fastapi>=0.110.0",
"uvicorn>=0.29.0",
"sse-starlette>=1.0.0",
"openai>=1.0.0",
# cryptography>=50.0.0: fixes PYSEC-2026-3552 / CVE-2026-69247 / GHSA-g6cj-pr64-35w5
"cryptography>=50.0.0",
# aiohttp>=3.14.3: fixes PYSEC-2026-3545/3546/3547 (CVE-2026-69244,
# CVE-2026-69243, CVE-2026-59881). Pinned as a direct dependency to force
# the resolver to select a patched version even though aiohttp is only
# pulled in transitively (e.g. via google-adk / langfuse).
"aiohttp>=3.14.3",
"pytest-cov>=7.1.0",
]
requires-python = ">=3.10,<3.13"
[dependency-groups]
dev = [
"freezegun>=1.5.0",
"pytest>=8.3.2",
"pytest-asyncio>=0.23.7",
"nest-asyncio>=1.6.0",
"respx>=0.22.0",
"scikit-learn>=1.4.0",
"pandas>=2.2.0",
"pip-licenses>=5.0.0",
"pip-audit>=2.10.0",
"fakeredis[lua]>=2.35.1",
"pytest-timeout>=2.4.0",
"bcrypt>=5.0.0",
# kfp: Kubeflow Pipelines SDK — required by test_pipeline_compilation.py
"kfp>=2.0,<3.0",
# pytest-xdist: parallel test execution — splits the 2259-test suite across
# CPU cores, reducing wall-clock time proportional to core count.
# --dist=loadfile keeps all tests from one module on the same worker so that
# module-level monkeypatches and singletons are not shared across processes.
"pytest-xdist>=3.5.0",
# pytest-randomly: randomizes test order to detect hidden test-order dependencies.
# Run with --randomly-seed=last to reproduce a failure.
# NOT added to pytest.ini addopts — keep random order opt-in so CI failures
# don't look flaky. Use `make test-random` or pass -p randomly --randomly-seed=0.
"pytest-randomly>=3.15.0",
"bandit>=1.7.0",
# Security: pin transitive deps to versions that fix known CVEs
# pyasn1 0.6.3: CVE-2026-59884/59885/59886 (DoS in BER/OID/Real decode) — fixed in 0.6.4
"pyasn1>=0.6.4",
# setuptools 82.0.1: CVE-2026-59890 (MANIFEST.in NFC/NFD bypass on macOS APFS) — fixed in 83.0.0
"setuptools>=83.0.0",
]
deployment = [
"absl-py>=2.2.1",
]
[project.optional-dependencies]
gateway = [
"grpcio>=1.78.0",
"protobuf>=5.26.1,<7.0.0",
"mcp>=0.1.0",
# PyJWT[crypto]: OIDC middleware (src/gateway/server/governance_middleware.py)
# imports `jwt` directly for JWKS-based token validation. Previously only
# pulled in transitively via mcp's own pyjwt[crypto] dependency — declared
# explicitly here so the requirement is not silently dropped if mcp's own
# dependency spec changes.
"PyJWT[crypto]>=2.9.0",
"nemoguardrails>=0.20.0,<1.0.0",
# pyahocorasick: O(n) Aho-Corasick automaton for the Tier-1 keyword scanner
# (src/gateway/governance/text_filter.py). Without this, text_filter falls back
# to an O(n*m) any() loop and logs a WARN on every import. The package is an
# optional performance dependency — the fallback is functionally correct but
# slower under high-throughput inference traffic.
"pyahocorasick>=2.0.0",
# NOTE: 'outlines' was removed — CVE-2025-69872 (diskcache pickle RCE).
# The guided_json FSM decoder runs server-side inside vLLM, not client-side.
# CAGE never imports the outlines package; vLLM bundles its own copy.
"presidio-analyzer>=2.2.361",
"presidio-anonymizer>=2.2.361",
"spacy>=3.8.11",
"en-core-web-sm",
"opentelemetry-instrumentation-fastapi>=0.58b0",
"opentelemetry-instrumentation-requests>=0.58b0",
# google-cloud-kms: CTRL_KMS_001 evidentiary-independence control.
# Required by src/gateway/governance/kms_signer.py's GCPKMSProvider for
# asymmetric HSM signing of governance decisions (asymmetricSign / getPublicKey).
# Without this, KMSGovernanceSigner.from_env() raises RuntimeError even when
# KMS_GOVERNANCE_KEY is set correctly.
"google-cloud-kms>=2.24.0",
]
finance = [
"yfinance>=0.2.0",
]
advisor = [
"cybernetic-governance-engine[finance]",
"langgraph>=1.1.0",
"langgraph-checkpoint-redis",
# langchain>=1.3.9: fixes GHSA-gr75-jv2w-4656 (prompt injection via
# tool-call message deserialization). Minimum bumped from 1.1.0.
"langchain>=1.3.9",
"langchain-core>=1.1.0",
"langchain-openai>=0.1.0",
"langchain-mcp-adapters>=0.2.0",
"tabulate>=0.9.0",
"opentelemetry-instrumentation-langchain>=0.52.0",
# Previously pip-installed outside uv in root Dockerfile — now declared here
"opentelemetry-exporter-gcp-trace",
"google-adk>=1.28.1",
]
gcs = [
"google-cloud-storage>=2.0.0",
]
s3 = [
"boto3>=1.35.0",
]
clickhouse = [
"clickhouse-connect>=0.7.0",
]
compliance = [
"cybernetic-governance-engine[gcs,s3,clickhouse]",
"PyYAML>=6.0.0",
"dowhy>=0.12",
]
langfuse = [
# From src/compliance_bridge/requirements.txt — previously pip-only
"langfuse>=2.0.0",
]
slm = [
# SLM Flask sidecar — moved from core mandatory deps
"flask>=3.0.0",
"sentence-transformers>=3.0.0",
]
lint = [
"ruff>=0.4.6",
"mypy>=1.15.0",
"codespell>=2.2.0",
"types-pyyaml>=6.0.12.20240917",
"types-requests>=2.32.0.20240914",
]
[tool.ruff]
line-length = 88
target-version = "py310"
exclude = [
"src/gateway/governance/vendor",
".github/",
]
[tool.ruff.lint]
select = [
"E", # pycodestyle
"F", # pyflakes
"W", # pycodestyle warnings
"I", # isort
"C4", # flake8-comprehensions
"B", # flake8-bugbear
"UP", # pyupgrade
"RUF", # ruff specific rules
]
ignore = [
"E501", # line too long — not enforced project-wide
# E402: module-level import not at top of file — legitimate pattern for scripts
# that manipulate sys.path before importing project modules (upload_to_gcs.py,
# sync_langfuse_prompts.py, manage_langfuse_prompts.py, replay_failed_scores.py,
# evaluate_langfuse_traces.py, config/settings.py conditional imports).
"E402",
# The following are genuine design patterns, not suppressions of bugs:
"B904", # raise-without-from-inside-except — intentional in retry helpers
"B006", # mutable-argument-default — intentional in some factory patterns
"W293", # whitespace-before-comment — cosmetic, auto-formatted by editors
"E701", # multiple-statements-on-one-line-colon — used in compact stubs
"E741", # ambiguous-variable-name — 'l', 'O', 'I' used in math/ML contexts
"B017", # assert-raises-exception — used in tests intentionally
"F821", # undefined-name — dynamic imports in generated proto/NeMo code
"B008", # function-call-in-default-argument — FastAPI Depends() pattern
# RUF rules — legitimate patterns in this codebase:
"RUF006", # asyncio-dangling-task — fire-and-forget telemetry tasks
"RUF012", # mutable-class-attributes-annotations — Pydantic model fields
"RUF013", # implicit-optional — PEP 484 style used throughout
"RUF015", # unnecessary-iterable-allocation-for-first-element — readability
"RUF043", # pytest-raises-without-match-metacharacters — test style choice
"RUF046", # unnecessary-cast-to-int — explicit casts for clarity
"RUF100", # unused-noqa — kept to avoid breaking CI on stale suppressions
# F401/C401: re-exported symbols in __init__ files and generator patterns
"F401", # imported-but-unused — re-exported symbols in __init__ files
"C401", # unnecessary-generator-set — style preference
]
[tool.ruff.lint.mccabe]
max-complexity = 15
[tool.ruff.lint.isort]
known-first-party = ["src"]
[tool.mypy]
# Strict flags disabled — pre-existing violations across 89 files present before
# mypy job was introduced. Tracked as POAM item LINT-001 for follow-on remediation.
disallow_untyped_calls = false
disallow_untyped_defs = true
disallow_incomplete_defs = false
no_implicit_optional = true
check_untyped_defs = true
disallow_subclassing_any = false
warn_incomplete_stub = false
warn_redundant_casts = true
warn_unused_ignores = false
warn_unreachable = false
follow_imports = "silent"
ignore_missing_imports = true
explicit_package_bases = true
disable_error_code = [
# Pre-existing errors in generated proto files and untyped src modules
"type-arg",
"valid-type",
"var-annotated",
"dict-item",
"type-var",
]
exclude = [
".venv",
"src/gateway/protos/",
"src/agentsight-ui/gateway_protos/",
"src/gateway/governance/vendor/",
]
[tool.bandit]
exclude_dirs = ["tests", "scripts", "examples"]
skips = ["B101", "B104"] # assert statements and 0.0.0.0 container interface binds are acceptable in this codebase
[tool.codespell]
ignore-words-list = "rouge"
skip = "./locust_env/*,uv.lock,.venv,./frontend,**/*.ipynb"
[build-system]
requires = ["uv_build>=0.8.14,<0.9.0"]
build-backend = "uv_build"
[tool.uv.build-backend]
module-root = "src"
[tool.setuptools.packages.find]
where = ["src"]
[[tool.uv.index]]
url = "https://pypi.org/simple"
default = true
[tool.uv.sources]
en-core-web-sm = { url = "https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl" }
[project.entry-points."cage.plugins"]
finance = "cage_finance.plugin:FinanceCagePlugin"