- Add _MixinBase abstract class to _helpers.py: declares _session(), _deserialize_attacker(), _assert_pending(), _check_and_bump_version(), and list_running_topology_deckies() so mypy can see cross-mixin contracts - Add _require(val, msg) helper for narrowing T | None → T - Inherit _MixinBase in all 26 leaf mixin classes - Wrap SQLAlchemy column method calls (.is_(), .like(), .notin_(), .in_(), .contains()) with col() from sqlmodel — fixes attr-defined false positives caused by pydantic plugin typing class-level fields as Python value types - Wrap select(Model.field) with select(col(Model.field)) for column projections - Add pyproject.toml [[tool.mypy.overrides]] to disable arg-type in sqlmodel_repo.*: pydantic plugin resolves .where(Model.field == v) as where(bool), a false positive; call-arg still catches real argument errors - Remove 9 stale # type: ignore comments (logging, helpers, credentials) - Fix telemetry.py traced() overload no-redef + misc - Fix logs.py datetime/str operator and nullable PK comparison with col() - sqlmodel_repo/ now has 0 mypy errors
165 lines
4.5 KiB
TOML
165 lines
4.5 KiB
TOML
[build-system]
|
|
requires = ["setuptools>=68", "wheel"]
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
[project]
|
|
name = "decnet"
|
|
version = "0.2.0"
|
|
description = "Deception network: deploy honeypot deckies that appear as real LAN hosts"
|
|
license = "GPL-3.0-or-later"
|
|
license-files = ["LICENSE"]
|
|
requires-python = ">=3.11"
|
|
classifiers = [
|
|
"Programming Language :: Python :: 3.11",
|
|
"Operating System :: POSIX :: Linux",
|
|
"Topic :: Security",
|
|
"Topic :: System :: Networking :: Monitoring",
|
|
"Development Status :: 4 - Beta",
|
|
]
|
|
dependencies = [
|
|
"typer[all]>=0.12",
|
|
"pydantic>=2.0",
|
|
"docker>=7.0",
|
|
"pyyaml>=6.0",
|
|
"jinja2>=3.1",
|
|
"fastapi>=0.110.0",
|
|
"uvicorn>=0.29.0",
|
|
"aiosqlite>=0.20.0",
|
|
"asyncmy>=0.2.11",
|
|
"PyJWT>=2.8.0",
|
|
"bcrypt>=4.1.0",
|
|
"psutil>=5.9.0",
|
|
"python-dotenv>=1.0.0",
|
|
"sqlmodel>=0.0.16",
|
|
"scapy>=2.6.1",
|
|
"orjson>=3.10",
|
|
"cryptography>=46.0.7",
|
|
"python-multipart>=0.0.20",
|
|
"httpx>=0.28.1",
|
|
"requests>=2.33.1",
|
|
"slowapi>=0.1.9",
|
|
"sqlite_vec>=0.1.9",
|
|
"Pillow>=12.2.0",
|
|
"lxml>=6.1.0",
|
|
"pikepdf>=10.5.1",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
tracing = [
|
|
"opentelemetry-api>=1.20.0",
|
|
"opentelemetry-sdk>=1.20.0",
|
|
"opentelemetry-exporter-otlp>=1.20.0",
|
|
"opentelemetry-instrumentation-fastapi>=0.41b0",
|
|
]
|
|
profile = [
|
|
"py-spy>=0.4.1",
|
|
"pyinstrument>=4.7",
|
|
"pytest-benchmark>=4.0",
|
|
"memray>=1.14 ; sys_platform == 'linux'",
|
|
"snakeviz>=2.2",
|
|
]
|
|
dev = [
|
|
"decnet[tracing,profile]",
|
|
"pytest>=9.0.3",
|
|
"ruff>=0.15.10",
|
|
"bandit>=1.9.4",
|
|
"pip>=26.0",
|
|
"pip-audit>=2.10.0",
|
|
"httpx>=0.28.1",
|
|
"hypothesis>=6.151.14",
|
|
"pytest-cov>=7.1.0",
|
|
"pytest-asyncio>=1.3.0",
|
|
"freezegun>=1.5.5",
|
|
"schemathesis>=4.15.1",
|
|
"pytest-xdist>=3.8.0",
|
|
"pytest-timeout>=2.4.0",
|
|
"flask>=3.1.3",
|
|
"twisted>=25.5.0",
|
|
"requests>=2.33.1",
|
|
"redis>=7.4.0",
|
|
"pymysql>=1.1.2",
|
|
"psycopg2-binary>=2.9.11",
|
|
"paho-mqtt>=2.1.0",
|
|
"pymongo>=4.16.0",
|
|
"locust>=2.29",
|
|
"gevent>=24.0",
|
|
"pydeps>=3.0.3",
|
|
"types-PyYAML>=6.0",
|
|
"mypy>=1.16,<1.20"
|
|
]
|
|
|
|
[project.scripts]
|
|
decnet = "decnet.cli:app"
|
|
|
|
[tool.pytest.ini_options]
|
|
asyncio_mode = "auto"
|
|
asyncio_debug = "true"
|
|
asyncio_default_fixture_loop_scope = "module"
|
|
addopts = "-m 'not fuzz and not live and not stress and not bench and not docker' -v -q -x -n logical --dist loadscope"
|
|
markers = [
|
|
"fuzz: hypothesis-based fuzz tests (slow, run with -m fuzz or -m '' for all)",
|
|
"live: live subprocess service tests (run with -m live)",
|
|
"live_docker: live Docker container tests (requires DECNET_LIVE_DOCKER=1)",
|
|
"stress: locust-based stress tests (run with -m stress)",
|
|
"bench: pytest-benchmark micro-benchmarks (run with -m bench)",
|
|
"docker: tests that build and run docker images (run with -m docker)",
|
|
]
|
|
filterwarnings = [
|
|
"ignore::pytest.PytestUnhandledThreadExceptionWarning",
|
|
"ignore::DeprecationWarning",
|
|
"ignore::RuntimeWarning",
|
|
]
|
|
|
|
[tool.coverage.run]
|
|
source = ["decnet"]
|
|
omit = ["*/tests/*", "*/templates/*"]
|
|
parallel = true
|
|
|
|
[tool.coverage.report]
|
|
show_missing = true
|
|
skip_covered = false
|
|
# Run with: pytest --cov --cov-report=term-missing
|
|
|
|
[tool.setuptools.packages.find]
|
|
where = ["."]
|
|
include = ["decnet*"]
|
|
|
|
[tool.setuptools.package-data]
|
|
# Ship docker build contexts + syslog_bridge.py as package data so they land
|
|
# in site-packages when agents install the bundle via `pip install`.
|
|
# canary/*.js + canary/package.json ship the Node-side toolchain manifest
|
|
# so `decnet canary-install-toolchain` can `npm install` post-install.
|
|
decnet = [
|
|
"templates/**/*",
|
|
"canary/_obfuscate_helper.js",
|
|
"canary/fingerprint_payload.js",
|
|
"canary/package.json",
|
|
]
|
|
|
|
[tool.bandit]
|
|
# Docker build contexts — code runs inside decoy containers, not in the
|
|
# master/agent process. Skipping keeps honeypot service scripts (hashlib.md5
|
|
# for JA3, /tmp/build in Dockerfile helpers, etc.) out of the scan.
|
|
exclude_dirs = [
|
|
"decnet/templates",
|
|
]
|
|
|
|
[tool.mypy]
|
|
plugins = [
|
|
"pydantic.mypy"
|
|
]
|
|
python_version = "3.11"
|
|
strict = false
|
|
ignore_missing_imports = true
|
|
check_untyped_defs = true
|
|
warn_redundant_casts = true
|
|
warn_unused_ignores = true
|
|
|
|
[[tool.mypy.overrides]]
|
|
# The pydantic plugin types SQLModel class-level field descriptors as their
|
|
# Python value types (str, bool, …) instead of InstrumentedAttribute. Every
|
|
# .where(Model.field == value) then becomes where(bool) — a false positive.
|
|
# Suppressing arg-type here; genuine argument errors are caught by call-arg.
|
|
module = "decnet.web.db.sqlmodel_repo.*"
|
|
disable_error_code = ["arg-type"]
|