-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyproject.toml
More file actions
237 lines (219 loc) · 8.84 KB
/
Copy pathpyproject.toml
File metadata and controls
237 lines (219 loc) · 8.84 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
[tool.ruff]
line-length = 100
exclude = [
"Сброс настроек COMET.py",
"Сброс настрок COMET.py",
"graph_route_example.py",
"vectordb/__init__.py",
".tmp",
"tests/pytest-cache-files-*",
"archive-legacy",
"reports",
"data",
]
[tool.ruff.lint]
# Incremental lint-ratchet (audit_claude_03_06_26.md §11 F6), each rule
# enforced after clearing every site:
# B904 exception chaining · B905 zip strict= · B009 getattr-constant
# RUF012 ClassVar · UP006/UP035 PEP 585 builtins (typing.Dict/List → dict/list)
# I import sorting (isort)
select = ["E", "F", "W", "B904", "B905", "B009", "RUF012", "UP006", "UP035", "I"]
ignore = ["E501"]
[tool.ruff.lint.per-file-ignores]
# api/app.py has a hand-tuned import layout that isort fights: split
# `from x import (a,b,c)` detaches per-name `# noqa: F401` on re-exports, and
# resorting the late router-registration block (deliberately after _lifespan,
# each `# noqa: E402`) breaks those suppressions. Left to the planned app.py
# decomposition (audit §11) rather than forcing isort here.
"api/app.py" = ["I001"]
[tool.pytest.ini_options]
markers = [
"integration: end-to-end integration tests",
]
norecursedirs = [".*", "build", "dist", "CVS", "_darcs", "{arch}", "*.egg", "venv", "pytest-cache-files-*", "archive-legacy", "data"]
[tool.coverage.run]
branch = true
source = [
"agent",
"api",
"auth",
"channels",
"config",
"db",
"evaluation",
"ingestion",
"llm",
"monitoring",
"tasks",
"tracing",
"utils",
"vectordb",
]
omit = [
"*/__pycache__/*",
"*/tests/*",
"scripts/*",
"archive-legacy/*",
"alembic/*",
"data/*",
".tmp/*",
"graph_route_example.py",
]
[tool.coverage.report]
# Honest baseline: 70.02% verified 2026-04-29 against full pytest+coverage suite
# (630 passed, 4 skipped). Gate raised after focused tests for
# evaluation/ragas_eval, vectordb/_base_manager, and benchmark_runner.
fail_under = 70
show_missing = true
skip_covered = false
exclude_lines = [
"pragma: no cover",
"if TYPE_CHECKING:",
"raise NotImplementedError",
"if __name__ == .__main__.:",
"\\.\\.\\.",
]
# ---------------------------------------------------------------------------
# Mypy — opt-in, not blocking. Run as `mypy auth db/models.py llm/providers`.
# The base config below is permissive; specific high-value modules below get
# strict treatment via [[tool.mypy.overrides]].
# ---------------------------------------------------------------------------
[tool.mypy]
python_version = "3.11"
ignore_missing_imports = true
follow_imports = "silent"
warn_unused_configs = true
warn_redundant_casts = true
show_error_codes = true
pretty = true
exclude = [
"archive-legacy/",
"alembic/versions/",
"data/",
"scripts/",
"tests/",
"graph_route_example.py",
"build/",
"dist/",
]
# Strict treatment for the smallest, highest-trust modules. Expand this list
# as the codebase converges on full type coverage.
[[tool.mypy.overrides]]
module = ["auth.*"]
disallow_untyped_defs = true
disallow_incomplete_defs = true
warn_return_any = true
warn_unused_ignores = true
no_implicit_optional = true
# llm.providers — strict mypy scope (was informational; promoted to strict
# 2026-04-27 after the runtime-typed-kwargs and Headers/Mapping fixes).
[[tool.mypy.overrides]]
module = ["llm.providers.*"]
disallow_untyped_defs = true
disallow_incomplete_defs = true
# db.* — strict scope. Promoted from db.models alone to the whole package
# (2026-06-13): db.engine/db.audit/db.crypto annotated (pgcrypto TypeDecorator
# returns ColumnElement; audit purge reads rowcount via getattr off the base
# Result type). Security-sensitive layer; keep it strict-clean.
[[tool.mypy.overrides]]
module = ["db.*"]
disallow_untyped_defs = true
disallow_incomplete_defs = true
# tasks.* and utils.* — strict scope (2026-06-13). Small infra/utility modules
# with full type coverage; promoted after annotating the *args/**kwargs proxies
# in utils.retry / utils.circuit_breaker. Expand as more modules converge.
[[tool.mypy.overrides]]
module = ["tasks.*", "utils.*"]
disallow_untyped_defs = true
disallow_incomplete_defs = true
# monitoring.* and channels.* — strict scope (2026-06-13). The optional
# prometheus_client dependency makes every metric global a "real class or
# _NoopMetric" union; declared once in a TYPE_CHECKING block per module so the
# import-present and import-absent assignment branches both type-check (no
# runtime change). channels also got imap/email payload narrowing.
[[tool.mypy.overrides]]
module = ["monitoring.*", "channels.*"]
disallow_untyped_defs = true
disallow_incomplete_defs = true
# tracing.* and ingestion.* — strict scope (2026-06-13). Observability +
# ingestion infra. tracing.otel follows the same optional-dependency shape as
# monitoring: the opentelemetry globals start as None and are rebound by
# _ensure_dependencies(), so they are typed Any (type-only, runtime unchanged).
# ingestion.pipeline's build_vector_store holds either the tenant-aware or the
# legacy callable (dispatched via inspect.signature), typed Callable[..., ...].
[[tool.mypy.overrides]]
module = ["tracing.*", "ingestion.*"]
disallow_untyped_defs = true
disallow_incomplete_defs = true
# evaluation.* — strict scope (2026-06-13). Offline/online eval framework.
# Type-only fixes: bind dict.get() results to locals before isinstance so the
# narrowing applies (online_evaluators), narrow None explicitly in drift, type
# the heterogeneous profile/result dicts as dict[str, Any], and annotate the
# duck-typed async `session` params (rollback_watcher) as Any.
[[tool.mypy.overrides]]
module = ["evaluation.*"]
disallow_untyped_defs = true
disallow_incomplete_defs = true
# agent modules — strict scope (Step 9).
[[tool.mypy.overrides]]
module = ["agent.state", "agent.prompts", "agent.prompt_registry", "agent.tools", "agent.graph"]
disallow_untyped_defs = true
disallow_incomplete_defs = true
# api.app — strict scope (2026-04-28). Promoted after a small typing pass:
# narrowed Optional access, dropped unused type:ignore on now-typed langchain
# imports, annotated getattr() fallbacks, and added a single arg-type ignore
# for Starlette's invariant exception-handler signature. Keep this module
# strict-clean; if you need to relax, fix the type instead.
[[tool.mypy.overrides]]
module = ["api.app"]
disallow_untyped_defs = true
disallow_incomplete_defs = true
warn_return_any = true
warn_unused_ignores = true
# api routers + helpers — strict scope (2026-06-14). The thin-shell modules
# extracted from api.app (Phase 2 / Step 8 refactor). Type-only pass: annotated
# the _async_session()/_log_audit() monkeypatch-indirection helpers and a few
# endpoint return types, narrowed None before .isoformat(), cast the
# object-typed analytics sort keys, annotated the rate_limit ImportError fallback
# stubs. Checked with --follow-imports=skip in the gates (these transitively
# import api.app via api._shared, whose full graph times out under mypy — same
# reason api.app itself uses that flag). No warn_return_any here: SSO endpoints
# return authlib's Any-typed redirect, which that flag would reject spuriously.
[[tool.mypy.overrides]]
module = ["api._shared", "api.correlation", "api.rate_limit", "api.routers.*"]
disallow_untyped_defs = true
disallow_incomplete_defs = true
no_implicit_optional = true
# vectordb.* — strict scope (2026-06-14). Vector-store managers. The package is
# already fully annotated, so this override is a ratchet (lock in the clean
# state), not a fix. Checked with --follow-imports=skip in the gates, alongside
# api.app: vectordb pulls langchain and sentence-transformers, whose full type
# graph spikes mypy memory (~2GB+, hangs low-RAM Windows boxes) — the same
# heavy-graph reason api.app uses that flag (there it is a timeout, here memory).
# Under skip those imports are Any, so warn_return_any is omitted: it would flag
# the langchain-returning helpers spuriously, exactly as noted for api.routers.
[[tool.mypy.overrides]]
module = ["vectordb.*"]
disallow_untyped_defs = true
disallow_incomplete_defs = true
no_implicit_optional = true
# ---------------------------------------------------------------------------
# Bandit — static security analysis. Run as `bandit -r . -c pyproject.toml`.
# ---------------------------------------------------------------------------
[tool.bandit]
exclude_dirs = [
"tests",
"archive-legacy",
"scripts",
"data",
"alembic/versions",
".tmp",
"reports",
]
# B608: hardcoded SQL expressions — every flagged occurrence in this codebase
# uses a parameterized query with `?` placeholders that are built from
# a whitelisted column/table list, not from user input. Verified
# 2026-04-26 audit. Skip globally.
# B310: urllib.urlopen — used only for an Ollama healthcheck on localhost
# with a 3-second timeout. No external attack surface.
skips = ["B608", "B310"]