Repository navigation
Expand file tree
/
Copy pathpyproject.toml
More file actions
260 lines (242 loc) · 8.34 KB
/
Copy pathpyproject.toml
File metadata and controls
260 lines (242 loc) · 8.34 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
[build-system]
# wheel ≥0.46 closes the path-traversal CVE in older versions
# (Finding 7.2). setuptools floor stays at 69 for the existing API.
requires = ["setuptools>=69.0", "wheel>=0.46"]
build-backend = "setuptools.build_meta"
[project]
name = "meow-decoder"
version = "1.0.0"
description = "🐱 Schrödinger's Yarn Ball - Optical air-gap transfer with quantum plausible deniability"
readme = "README.md"
requires-python = ">=3.10"
license = "CC-BY-NC-SA-4.0"
authors = [{ name = "Paul Clark", email = "systemslibrarian@gmail.com" }]
keywords = [
"encryption",
"air-gap",
"qr-code",
"security",
"cryptography",
"post-quantum",
"optical-transfer",
]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Security :: Cryptography",
]
dependencies = [
"cryptography>=46.0.5",
"Pillow>=12.1.1",
"opencv-python>=4.8.1.78",
"pyzbar>=0.1.9",
"qrcode[pil]>=8.2",
"argon2-cffi>=25.1.0",
"numpy>=1.24.0",
"pynacl>=1.6.2",
]
[project.optional-dependencies]
quantum = ["liboqs-python>=0.9.0"]
gui = ["dearpygui>=1.10.0", "cairosvg>=2.7.0"]
streaming = ["psutil>=5.9.0"]
sounds = ["playsound>=1.3.0"]
progress = ["tqdm>=4.66.0"]
dev = [
"pytest>=7.4.0",
"pytest-cov>=4.1.0",
"pytest-xdist>=3.5.0",
"hypothesis>=6.100.0,<6.169.0",
"coverage[toml]>=7.4.0",
"black>=24.3.0",
"flake8>=6.1.0",
"mypy>=1.5.0",
"bandit>=1.7.5",
]
all = [
"liboqs-python>=0.9.0",
"dearpygui>=1.10.0",
"cairosvg>=2.7.0",
"psutil>=5.9.0",
"playsound>=1.3.0",
"tqdm>=4.66.0",
]
[project.scripts]
meow-encode = "meow_decoder.encode:main"
meow-decode-gif = "meow_decoder.decode_gif:main"
meow-shamir = "meow_decoder.shamir_split:main"
meow-schrodinger-encode = "meow_decoder.schrodinger_encode:main"
meow-deadmans-switch = "meow_decoder.deadmans_switch_cli:main"
# Optional scripts (uncomment if you install the gui dependencies):
# meow-webcam = "meow_decoder.decode_webcam_with_resume:main"
# meow-dashboard = "meow_decoder.meow_dashboard_demo:main"
[project.urls]
Homepage = "https://github.com/systemslibrarian/meow-decoder"
Documentation = "https://github.com/systemslibrarian/meow-decoder/tree/main/docs"
Repository = "https://github.com/systemslibrarian/meow-decoder"
"Bug Tracker" = "https://github.com/systemslibrarian/meow-decoder/issues"
Changelog = "https://github.com/systemslibrarian/meow-decoder/blob/main/CHANGELOG.md"
[tool.black]
line-length = 100
target-version = ['py310', 'py311', 'py312', 'py313']
include = '\.pyi?$'
[tool.pytest.ini_options]
testpaths = ["tests"]
norecursedirs = ["archive", "_archive", "__pycache__", ".git", ".hypothesis", "htmlcov", "node_modules", "target", "test-results", "releases", "playwright-report"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = "-v --strict-markers --cov=meow_decoder --cov-config=.coveragerc --cov-report=html --cov-report=term"
markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
"security: security-critical tests (crypto, auth, tamper detection)",
"adversarial: adversarial / abuse-case tests (malformed input, fuzzing)",
"crypto: cryptographic primitive and protocol tests",
"fuzz: fuzz / property-based tests (may be slow)",
"property: property-based invariant tests",
"integration: end-to-end integration tests",
"cat: cat-themed error and UX tests",
"deprecated: tests for deprecated modules scheduled for removal (deselect with '-m \"not deprecated\"')",
]
[tool.coverage.run]
# Coverage uses .coveragerc as primary config (source = meow_decoder with omits)
# This section is kept for documentation only — .coveragerc takes precedence
branch = true
source = ["meow_decoder"]
# COVERAGE STRATEGY:
# Primary config: .coveragerc (source = meow_decoder, with omit patterns)
# Security gate: .coveragerc-security (5 Tier 1 modules, fail-under=85)
#
# TIER 1 (Crypto-Critical): 95-100% target
# crypto.py, crypto_backend.py, constant_time.py, fountain.py, frame_mac.py
# TIER 2 (CLI/I/O): 90%+ target
# encode.py, decode_gif.py, config.py, gif_handler.py
[tool.coverage.xml]
[tool.coverage.report]
fail_under = 0
show_missing = true
skip_covered = false
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if __name__ == .__main__.:",
"raise NotImplementedError",
"if TYPE_CHECKING:",
# Debug/development code paths
"if _TEST_MODE:",
"if verbose:",
"if args.verbose:",
]
# Per-file coverage requirements for crypto-critical paths
# These files MUST maintain high coverage
# TODO: Uncomment when coverage targets are met
# [tool.coverage.report.partial_branches]
# crypto.py = 95
# crypto_backend.py = 95
# fountain.py = 95
# frame_mac.py = 95
[tool.coverage.html]
directory = "htmlcov"
# NOTE: Hypothesis profiles are registered in tests/conftest.py with database=None
# to avoid SimpleNamespace hashing issues in Hypothesis 6.123+.
# Do NOT add [tool.hypothesis] sections here.
[tool.mypy]
python_version = "3.10"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = false
ignore_missing_imports = true
# Per-module overrides for experimental/legacy code
[[tool.mypy.overrides]]
module = [
"meow_decoder.encode_DEBUG",
"meow_decoder.decode_webcam_with_resume",
"meow_decoder.multi_secret",
"meow_decoder.profiling_improved",
"meow_decoder.encode",
"meow_decoder.resume_secured",
"meow_decoder.streaming_crypto",
"meow_decoder.secure_bridge",
"meow_decoder.gif_handler",
"meow_decoder.hardware_integration",
"meow_decoder.hardware_keys",
"meow_decoder.high_security",
"meow_decoder.pq_signatures",
"meow_decoder.pq_hybrid",
"meow_decoder.double_ratchet",
"meow_decoder.catnip_fountain",
"meow_decoder.clowder_decode",
"meow_decoder.metadata_obfuscation",
"meow_decoder.spec_v12.key_management",
"meow_decoder.x25519_forward_secrecy",
"meow_decoder.logo_eyes",
"meow_decoder.deadmans_switch_cli",
"meow_decoder.decode_gif",
"meow_decoder.progress",
"meow_decoder.progress_bar",
"meow_decoder.webcam_enhanced",
"meow_decoder.crypto_backend",
"meow_decoder.crypto",
"meow_decoder.fountain",
# Modules with platform-specific (Windows/ctypes) or pre-existing type errors:
"meow_decoder.adversarial_carrier",
"meow_decoder.constant_time",
"meow_decoder.decorrelation",
"meow_decoder.dual_stream",
"meow_decoder.env_safety",
"meow_decoder.expiry",
"meow_decoder.forensic_cleanup",
"meow_decoder.manifest_signing",
"meow_decoder.memory_guard",
"meow_decoder.pq_ratchet_beacon",
"meow_decoder.ratchet",
"meow_decoder.secure_input",
"meow_decoder.secure_keyboard",
"meow_decoder.shamir_split",
"meow_decoder.size_normalizer",
"meow_decoder.source_cleanup",
"meow_decoder.stego_multilayer",
]
ignore_errors = true
[tool.mutmut]
paths_to_mutate = "meow_decoder/"
tests_dir = "tests/"
runner = "python -m pytest -x --timeout=30"
dict_synonyms = "Struct,NamedStruct"
# Bandit: even though CI invokes `bandit -r meow_decoder/` (which now
# never sees archive/ since the move out of the package), defend
# against `bandit -r .` runs by some developer locally.
[tool.bandit]
# gemini #7 — keep bandit scoped to current production surfaces.
# Excludes historical / generated / packaging dirs that aren't part of
# the live security boundary.
exclude_dirs = [
"archive",
"tests/_archive",
"node_modules",
"target",
".venv",
"venv",
"htmlcov",
"test-results",
"playwright-report",
"releases",
"build",
"dist",
".pytest_cache",
".hypothesis",
".mypy_cache",
]
# NOTE: flake8 config lives in .flake8 (flake8 does not read pyproject.toml)
[tool.setuptools.packages.find]
where = ["."]
include = ["meow_decoder*"]
# `archive/` lives at the repo root and is not a `meow_decoder*` package,
# so `include = ["meow_decoder*"]` already excludes it. Keep the legacy
# `meow_decoder._archive*` entry harmlessly listed — it acts as a guard
# in case someone re-introduces a `_archive/` subpackage by mistake.
exclude = ["assets*", "sounds*", "legacy_py*", "archive*", "meow_decoder._archive*"]