oscura 0.0.1__py3-none-any.whl → 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) hide show
  1. oscura/__init__.py +813 -8
  2. oscura/__main__.py +392 -0
  3. oscura/analyzers/__init__.py +37 -0
  4. oscura/analyzers/digital/__init__.py +177 -0
  5. oscura/analyzers/digital/bus.py +691 -0
  6. oscura/analyzers/digital/clock.py +805 -0
  7. oscura/analyzers/digital/correlation.py +720 -0
  8. oscura/analyzers/digital/edges.py +632 -0
  9. oscura/analyzers/digital/extraction.py +413 -0
  10. oscura/analyzers/digital/quality.py +878 -0
  11. oscura/analyzers/digital/signal_quality.py +877 -0
  12. oscura/analyzers/digital/thresholds.py +708 -0
  13. oscura/analyzers/digital/timing.py +1104 -0
  14. oscura/analyzers/eye/__init__.py +46 -0
  15. oscura/analyzers/eye/diagram.py +434 -0
  16. oscura/analyzers/eye/metrics.py +555 -0
  17. oscura/analyzers/jitter/__init__.py +83 -0
  18. oscura/analyzers/jitter/ber.py +333 -0
  19. oscura/analyzers/jitter/decomposition.py +759 -0
  20. oscura/analyzers/jitter/measurements.py +413 -0
  21. oscura/analyzers/jitter/spectrum.py +220 -0
  22. oscura/analyzers/measurements.py +40 -0
  23. oscura/analyzers/packet/__init__.py +171 -0
  24. oscura/analyzers/packet/daq.py +1077 -0
  25. oscura/analyzers/packet/metrics.py +437 -0
  26. oscura/analyzers/packet/parser.py +327 -0
  27. oscura/analyzers/packet/payload.py +2156 -0
  28. oscura/analyzers/packet/payload_analysis.py +1312 -0
  29. oscura/analyzers/packet/payload_extraction.py +236 -0
  30. oscura/analyzers/packet/payload_patterns.py +670 -0
  31. oscura/analyzers/packet/stream.py +359 -0
  32. oscura/analyzers/patterns/__init__.py +266 -0
  33. oscura/analyzers/patterns/clustering.py +1036 -0
  34. oscura/analyzers/patterns/discovery.py +539 -0
  35. oscura/analyzers/patterns/learning.py +797 -0
  36. oscura/analyzers/patterns/matching.py +1091 -0
  37. oscura/analyzers/patterns/periodic.py +650 -0
  38. oscura/analyzers/patterns/sequences.py +767 -0
  39. oscura/analyzers/power/__init__.py +116 -0
  40. oscura/analyzers/power/ac_power.py +391 -0
  41. oscura/analyzers/power/basic.py +383 -0
  42. oscura/analyzers/power/conduction.py +314 -0
  43. oscura/analyzers/power/efficiency.py +297 -0
  44. oscura/analyzers/power/ripple.py +356 -0
  45. oscura/analyzers/power/soa.py +372 -0
  46. oscura/analyzers/power/switching.py +479 -0
  47. oscura/analyzers/protocol/__init__.py +150 -0
  48. oscura/analyzers/protocols/__init__.py +150 -0
  49. oscura/analyzers/protocols/base.py +500 -0
  50. oscura/analyzers/protocols/can.py +620 -0
  51. oscura/analyzers/protocols/can_fd.py +448 -0
  52. oscura/analyzers/protocols/flexray.py +405 -0
  53. oscura/analyzers/protocols/hdlc.py +399 -0
  54. oscura/analyzers/protocols/i2c.py +368 -0
  55. oscura/analyzers/protocols/i2s.py +296 -0
  56. oscura/analyzers/protocols/jtag.py +393 -0
  57. oscura/analyzers/protocols/lin.py +445 -0
  58. oscura/analyzers/protocols/manchester.py +333 -0
  59. oscura/analyzers/protocols/onewire.py +501 -0
  60. oscura/analyzers/protocols/spi.py +334 -0
  61. oscura/analyzers/protocols/swd.py +325 -0
  62. oscura/analyzers/protocols/uart.py +393 -0
  63. oscura/analyzers/protocols/usb.py +495 -0
  64. oscura/analyzers/signal_integrity/__init__.py +63 -0
  65. oscura/analyzers/signal_integrity/embedding.py +294 -0
  66. oscura/analyzers/signal_integrity/equalization.py +370 -0
  67. oscura/analyzers/signal_integrity/sparams.py +484 -0
  68. oscura/analyzers/spectral/__init__.py +53 -0
  69. oscura/analyzers/spectral/chunked.py +273 -0
  70. oscura/analyzers/spectral/chunked_fft.py +571 -0
  71. oscura/analyzers/spectral/chunked_wavelet.py +391 -0
  72. oscura/analyzers/spectral/fft.py +92 -0
  73. oscura/analyzers/statistical/__init__.py +250 -0
  74. oscura/analyzers/statistical/checksum.py +923 -0
  75. oscura/analyzers/statistical/chunked_corr.py +228 -0
  76. oscura/analyzers/statistical/classification.py +778 -0
  77. oscura/analyzers/statistical/entropy.py +1113 -0
  78. oscura/analyzers/statistical/ngrams.py +614 -0
  79. oscura/analyzers/statistics/__init__.py +119 -0
  80. oscura/analyzers/statistics/advanced.py +885 -0
  81. oscura/analyzers/statistics/basic.py +263 -0
  82. oscura/analyzers/statistics/correlation.py +630 -0
  83. oscura/analyzers/statistics/distribution.py +298 -0
  84. oscura/analyzers/statistics/outliers.py +463 -0
  85. oscura/analyzers/statistics/streaming.py +93 -0
  86. oscura/analyzers/statistics/trend.py +520 -0
  87. oscura/analyzers/validation.py +598 -0
  88. oscura/analyzers/waveform/__init__.py +36 -0
  89. oscura/analyzers/waveform/measurements.py +943 -0
  90. oscura/analyzers/waveform/measurements_with_uncertainty.py +371 -0
  91. oscura/analyzers/waveform/spectral.py +1689 -0
  92. oscura/analyzers/waveform/wavelets.py +298 -0
  93. oscura/api/__init__.py +62 -0
  94. oscura/api/dsl.py +538 -0
  95. oscura/api/fluent.py +571 -0
  96. oscura/api/operators.py +498 -0
  97. oscura/api/optimization.py +392 -0
  98. oscura/api/profiling.py +396 -0
  99. oscura/automotive/__init__.py +73 -0
  100. oscura/automotive/can/__init__.py +52 -0
  101. oscura/automotive/can/analysis.py +356 -0
  102. oscura/automotive/can/checksum.py +250 -0
  103. oscura/automotive/can/correlation.py +212 -0
  104. oscura/automotive/can/discovery.py +355 -0
  105. oscura/automotive/can/message_wrapper.py +375 -0
  106. oscura/automotive/can/models.py +385 -0
  107. oscura/automotive/can/patterns.py +381 -0
  108. oscura/automotive/can/session.py +452 -0
  109. oscura/automotive/can/state_machine.py +300 -0
  110. oscura/automotive/can/stimulus_response.py +461 -0
  111. oscura/automotive/dbc/__init__.py +15 -0
  112. oscura/automotive/dbc/generator.py +156 -0
  113. oscura/automotive/dbc/parser.py +146 -0
  114. oscura/automotive/dtc/__init__.py +30 -0
  115. oscura/automotive/dtc/database.py +3036 -0
  116. oscura/automotive/j1939/__init__.py +14 -0
  117. oscura/automotive/j1939/decoder.py +745 -0
  118. oscura/automotive/loaders/__init__.py +35 -0
  119. oscura/automotive/loaders/asc.py +98 -0
  120. oscura/automotive/loaders/blf.py +77 -0
  121. oscura/automotive/loaders/csv_can.py +136 -0
  122. oscura/automotive/loaders/dispatcher.py +136 -0
  123. oscura/automotive/loaders/mdf.py +331 -0
  124. oscura/automotive/loaders/pcap.py +132 -0
  125. oscura/automotive/obd/__init__.py +14 -0
  126. oscura/automotive/obd/decoder.py +707 -0
  127. oscura/automotive/uds/__init__.py +48 -0
  128. oscura/automotive/uds/decoder.py +265 -0
  129. oscura/automotive/uds/models.py +64 -0
  130. oscura/automotive/visualization.py +369 -0
  131. oscura/batch/__init__.py +55 -0
  132. oscura/batch/advanced.py +627 -0
  133. oscura/batch/aggregate.py +300 -0
  134. oscura/batch/analyze.py +139 -0
  135. oscura/batch/logging.py +487 -0
  136. oscura/batch/metrics.py +556 -0
  137. oscura/builders/__init__.py +41 -0
  138. oscura/builders/signal_builder.py +1131 -0
  139. oscura/cli/__init__.py +14 -0
  140. oscura/cli/batch.py +339 -0
  141. oscura/cli/characterize.py +273 -0
  142. oscura/cli/compare.py +775 -0
  143. oscura/cli/decode.py +551 -0
  144. oscura/cli/main.py +247 -0
  145. oscura/cli/shell.py +350 -0
  146. oscura/comparison/__init__.py +66 -0
  147. oscura/comparison/compare.py +397 -0
  148. oscura/comparison/golden.py +487 -0
  149. oscura/comparison/limits.py +391 -0
  150. oscura/comparison/mask.py +434 -0
  151. oscura/comparison/trace_diff.py +30 -0
  152. oscura/comparison/visualization.py +481 -0
  153. oscura/compliance/__init__.py +70 -0
  154. oscura/compliance/advanced.py +756 -0
  155. oscura/compliance/masks.py +363 -0
  156. oscura/compliance/reporting.py +483 -0
  157. oscura/compliance/testing.py +298 -0
  158. oscura/component/__init__.py +38 -0
  159. oscura/component/impedance.py +365 -0
  160. oscura/component/reactive.py +598 -0
  161. oscura/component/transmission_line.py +312 -0
  162. oscura/config/__init__.py +191 -0
  163. oscura/config/defaults.py +254 -0
  164. oscura/config/loader.py +348 -0
  165. oscura/config/memory.py +271 -0
  166. oscura/config/migration.py +458 -0
  167. oscura/config/pipeline.py +1077 -0
  168. oscura/config/preferences.py +530 -0
  169. oscura/config/protocol.py +875 -0
  170. oscura/config/schema.py +713 -0
  171. oscura/config/settings.py +420 -0
  172. oscura/config/thresholds.py +599 -0
  173. oscura/convenience.py +457 -0
  174. oscura/core/__init__.py +299 -0
  175. oscura/core/audit.py +457 -0
  176. oscura/core/backend_selector.py +405 -0
  177. oscura/core/cache.py +590 -0
  178. oscura/core/cancellation.py +439 -0
  179. oscura/core/confidence.py +225 -0
  180. oscura/core/config.py +506 -0
  181. oscura/core/correlation.py +216 -0
  182. oscura/core/cross_domain.py +422 -0
  183. oscura/core/debug.py +301 -0
  184. oscura/core/edge_cases.py +541 -0
  185. oscura/core/exceptions.py +535 -0
  186. oscura/core/gpu_backend.py +523 -0
  187. oscura/core/lazy.py +832 -0
  188. oscura/core/log_query.py +540 -0
  189. oscura/core/logging.py +931 -0
  190. oscura/core/logging_advanced.py +952 -0
  191. oscura/core/memoize.py +171 -0
  192. oscura/core/memory_check.py +274 -0
  193. oscura/core/memory_guard.py +290 -0
  194. oscura/core/memory_limits.py +336 -0
  195. oscura/core/memory_monitor.py +453 -0
  196. oscura/core/memory_progress.py +465 -0
  197. oscura/core/memory_warnings.py +315 -0
  198. oscura/core/numba_backend.py +362 -0
  199. oscura/core/performance.py +352 -0
  200. oscura/core/progress.py +524 -0
  201. oscura/core/provenance.py +358 -0
  202. oscura/core/results.py +331 -0
  203. oscura/core/types.py +504 -0
  204. oscura/core/uncertainty.py +383 -0
  205. oscura/discovery/__init__.py +52 -0
  206. oscura/discovery/anomaly_detector.py +672 -0
  207. oscura/discovery/auto_decoder.py +415 -0
  208. oscura/discovery/comparison.py +497 -0
  209. oscura/discovery/quality_validator.py +528 -0
  210. oscura/discovery/signal_detector.py +769 -0
  211. oscura/dsl/__init__.py +73 -0
  212. oscura/dsl/commands.py +246 -0
  213. oscura/dsl/interpreter.py +455 -0
  214. oscura/dsl/parser.py +689 -0
  215. oscura/dsl/repl.py +172 -0
  216. oscura/exceptions.py +59 -0
  217. oscura/exploratory/__init__.py +111 -0
  218. oscura/exploratory/error_recovery.py +642 -0
  219. oscura/exploratory/fuzzy.py +513 -0
  220. oscura/exploratory/fuzzy_advanced.py +786 -0
  221. oscura/exploratory/legacy.py +831 -0
  222. oscura/exploratory/parse.py +358 -0
  223. oscura/exploratory/recovery.py +275 -0
  224. oscura/exploratory/sync.py +382 -0
  225. oscura/exploratory/unknown.py +707 -0
  226. oscura/export/__init__.py +25 -0
  227. oscura/export/wireshark/README.md +265 -0
  228. oscura/export/wireshark/__init__.py +47 -0
  229. oscura/export/wireshark/generator.py +312 -0
  230. oscura/export/wireshark/lua_builder.py +159 -0
  231. oscura/export/wireshark/templates/dissector.lua.j2 +92 -0
  232. oscura/export/wireshark/type_mapping.py +165 -0
  233. oscura/export/wireshark/validator.py +105 -0
  234. oscura/exporters/__init__.py +94 -0
  235. oscura/exporters/csv.py +303 -0
  236. oscura/exporters/exporters.py +44 -0
  237. oscura/exporters/hdf5.py +219 -0
  238. oscura/exporters/html_export.py +701 -0
  239. oscura/exporters/json_export.py +291 -0
  240. oscura/exporters/markdown_export.py +367 -0
  241. oscura/exporters/matlab_export.py +354 -0
  242. oscura/exporters/npz_export.py +219 -0
  243. oscura/exporters/spice_export.py +210 -0
  244. oscura/extensibility/__init__.py +131 -0
  245. oscura/extensibility/docs.py +752 -0
  246. oscura/extensibility/extensions.py +1125 -0
  247. oscura/extensibility/logging.py +259 -0
  248. oscura/extensibility/measurements.py +485 -0
  249. oscura/extensibility/plugins.py +414 -0
  250. oscura/extensibility/registry.py +346 -0
  251. oscura/extensibility/templates.py +913 -0
  252. oscura/extensibility/validation.py +651 -0
  253. oscura/filtering/__init__.py +89 -0
  254. oscura/filtering/base.py +563 -0
  255. oscura/filtering/convenience.py +564 -0
  256. oscura/filtering/design.py +725 -0
  257. oscura/filtering/filters.py +32 -0
  258. oscura/filtering/introspection.py +605 -0
  259. oscura/guidance/__init__.py +24 -0
  260. oscura/guidance/recommender.py +429 -0
  261. oscura/guidance/wizard.py +518 -0
  262. oscura/inference/__init__.py +251 -0
  263. oscura/inference/active_learning/README.md +153 -0
  264. oscura/inference/active_learning/__init__.py +38 -0
  265. oscura/inference/active_learning/lstar.py +257 -0
  266. oscura/inference/active_learning/observation_table.py +230 -0
  267. oscura/inference/active_learning/oracle.py +78 -0
  268. oscura/inference/active_learning/teachers/__init__.py +15 -0
  269. oscura/inference/active_learning/teachers/simulator.py +192 -0
  270. oscura/inference/adaptive_tuning.py +453 -0
  271. oscura/inference/alignment.py +653 -0
  272. oscura/inference/bayesian.py +943 -0
  273. oscura/inference/binary.py +1016 -0
  274. oscura/inference/crc_reverse.py +711 -0
  275. oscura/inference/logic.py +288 -0
  276. oscura/inference/message_format.py +1305 -0
  277. oscura/inference/protocol.py +417 -0
  278. oscura/inference/protocol_dsl.py +1084 -0
  279. oscura/inference/protocol_library.py +1230 -0
  280. oscura/inference/sequences.py +809 -0
  281. oscura/inference/signal_intelligence.py +1509 -0
  282. oscura/inference/spectral.py +215 -0
  283. oscura/inference/state_machine.py +634 -0
  284. oscura/inference/stream.py +918 -0
  285. oscura/integrations/__init__.py +59 -0
  286. oscura/integrations/llm.py +1827 -0
  287. oscura/jupyter/__init__.py +32 -0
  288. oscura/jupyter/display.py +268 -0
  289. oscura/jupyter/magic.py +334 -0
  290. oscura/loaders/__init__.py +526 -0
  291. oscura/loaders/binary.py +69 -0
  292. oscura/loaders/configurable.py +1255 -0
  293. oscura/loaders/csv.py +26 -0
  294. oscura/loaders/csv_loader.py +473 -0
  295. oscura/loaders/hdf5.py +9 -0
  296. oscura/loaders/hdf5_loader.py +510 -0
  297. oscura/loaders/lazy.py +370 -0
  298. oscura/loaders/mmap_loader.py +583 -0
  299. oscura/loaders/numpy_loader.py +436 -0
  300. oscura/loaders/pcap.py +432 -0
  301. oscura/loaders/preprocessing.py +368 -0
  302. oscura/loaders/rigol.py +287 -0
  303. oscura/loaders/sigrok.py +321 -0
  304. oscura/loaders/tdms.py +367 -0
  305. oscura/loaders/tektronix.py +711 -0
  306. oscura/loaders/validation.py +584 -0
  307. oscura/loaders/vcd.py +464 -0
  308. oscura/loaders/wav.py +233 -0
  309. oscura/math/__init__.py +45 -0
  310. oscura/math/arithmetic.py +824 -0
  311. oscura/math/interpolation.py +413 -0
  312. oscura/onboarding/__init__.py +39 -0
  313. oscura/onboarding/help.py +498 -0
  314. oscura/onboarding/tutorials.py +405 -0
  315. oscura/onboarding/wizard.py +466 -0
  316. oscura/optimization/__init__.py +19 -0
  317. oscura/optimization/parallel.py +440 -0
  318. oscura/optimization/search.py +532 -0
  319. oscura/pipeline/__init__.py +43 -0
  320. oscura/pipeline/base.py +338 -0
  321. oscura/pipeline/composition.py +242 -0
  322. oscura/pipeline/parallel.py +448 -0
  323. oscura/pipeline/pipeline.py +375 -0
  324. oscura/pipeline/reverse_engineering.py +1119 -0
  325. oscura/plugins/__init__.py +122 -0
  326. oscura/plugins/base.py +272 -0
  327. oscura/plugins/cli.py +497 -0
  328. oscura/plugins/discovery.py +411 -0
  329. oscura/plugins/isolation.py +418 -0
  330. oscura/plugins/lifecycle.py +959 -0
  331. oscura/plugins/manager.py +493 -0
  332. oscura/plugins/registry.py +421 -0
  333. oscura/plugins/versioning.py +372 -0
  334. oscura/py.typed +0 -0
  335. oscura/quality/__init__.py +65 -0
  336. oscura/quality/ensemble.py +740 -0
  337. oscura/quality/explainer.py +338 -0
  338. oscura/quality/scoring.py +616 -0
  339. oscura/quality/warnings.py +456 -0
  340. oscura/reporting/__init__.py +248 -0
  341. oscura/reporting/advanced.py +1234 -0
  342. oscura/reporting/analyze.py +448 -0
  343. oscura/reporting/argument_preparer.py +596 -0
  344. oscura/reporting/auto_report.py +507 -0
  345. oscura/reporting/batch.py +615 -0
  346. oscura/reporting/chart_selection.py +223 -0
  347. oscura/reporting/comparison.py +330 -0
  348. oscura/reporting/config.py +615 -0
  349. oscura/reporting/content/__init__.py +39 -0
  350. oscura/reporting/content/executive.py +127 -0
  351. oscura/reporting/content/filtering.py +191 -0
  352. oscura/reporting/content/minimal.py +257 -0
  353. oscura/reporting/content/verbosity.py +162 -0
  354. oscura/reporting/core.py +508 -0
  355. oscura/reporting/core_formats/__init__.py +17 -0
  356. oscura/reporting/core_formats/multi_format.py +210 -0
  357. oscura/reporting/engine.py +836 -0
  358. oscura/reporting/export.py +366 -0
  359. oscura/reporting/formatting/__init__.py +129 -0
  360. oscura/reporting/formatting/emphasis.py +81 -0
  361. oscura/reporting/formatting/numbers.py +403 -0
  362. oscura/reporting/formatting/standards.py +55 -0
  363. oscura/reporting/formatting.py +466 -0
  364. oscura/reporting/html.py +578 -0
  365. oscura/reporting/index.py +590 -0
  366. oscura/reporting/multichannel.py +296 -0
  367. oscura/reporting/output.py +379 -0
  368. oscura/reporting/pdf.py +373 -0
  369. oscura/reporting/plots.py +731 -0
  370. oscura/reporting/pptx_export.py +360 -0
  371. oscura/reporting/renderers/__init__.py +11 -0
  372. oscura/reporting/renderers/pdf.py +94 -0
  373. oscura/reporting/sections.py +471 -0
  374. oscura/reporting/standards.py +680 -0
  375. oscura/reporting/summary_generator.py +368 -0
  376. oscura/reporting/tables.py +397 -0
  377. oscura/reporting/template_system.py +724 -0
  378. oscura/reporting/templates/__init__.py +15 -0
  379. oscura/reporting/templates/definition.py +205 -0
  380. oscura/reporting/templates/index.html +649 -0
  381. oscura/reporting/templates/index.md +173 -0
  382. oscura/schemas/__init__.py +158 -0
  383. oscura/schemas/bus_configuration.json +322 -0
  384. oscura/schemas/device_mapping.json +182 -0
  385. oscura/schemas/packet_format.json +418 -0
  386. oscura/schemas/protocol_definition.json +363 -0
  387. oscura/search/__init__.py +16 -0
  388. oscura/search/anomaly.py +292 -0
  389. oscura/search/context.py +149 -0
  390. oscura/search/pattern.py +160 -0
  391. oscura/session/__init__.py +34 -0
  392. oscura/session/annotations.py +289 -0
  393. oscura/session/history.py +313 -0
  394. oscura/session/session.py +445 -0
  395. oscura/streaming/__init__.py +43 -0
  396. oscura/streaming/chunked.py +611 -0
  397. oscura/streaming/progressive.py +393 -0
  398. oscura/streaming/realtime.py +622 -0
  399. oscura/testing/__init__.py +54 -0
  400. oscura/testing/synthetic.py +808 -0
  401. oscura/triggering/__init__.py +68 -0
  402. oscura/triggering/base.py +229 -0
  403. oscura/triggering/edge.py +353 -0
  404. oscura/triggering/pattern.py +344 -0
  405. oscura/triggering/pulse.py +581 -0
  406. oscura/triggering/window.py +453 -0
  407. oscura/ui/__init__.py +48 -0
  408. oscura/ui/formatters.py +526 -0
  409. oscura/ui/progressive_display.py +340 -0
  410. oscura/utils/__init__.py +99 -0
  411. oscura/utils/autodetect.py +338 -0
  412. oscura/utils/buffer.py +389 -0
  413. oscura/utils/lazy.py +407 -0
  414. oscura/utils/lazy_imports.py +147 -0
  415. oscura/utils/memory.py +836 -0
  416. oscura/utils/memory_advanced.py +1326 -0
  417. oscura/utils/memory_extensions.py +465 -0
  418. oscura/utils/progressive.py +352 -0
  419. oscura/utils/windowing.py +362 -0
  420. oscura/visualization/__init__.py +321 -0
  421. oscura/visualization/accessibility.py +526 -0
  422. oscura/visualization/annotations.py +374 -0
  423. oscura/visualization/axis_scaling.py +305 -0
  424. oscura/visualization/colors.py +453 -0
  425. oscura/visualization/digital.py +337 -0
  426. oscura/visualization/eye.py +420 -0
  427. oscura/visualization/histogram.py +281 -0
  428. oscura/visualization/interactive.py +858 -0
  429. oscura/visualization/jitter.py +702 -0
  430. oscura/visualization/keyboard.py +394 -0
  431. oscura/visualization/layout.py +365 -0
  432. oscura/visualization/optimization.py +1028 -0
  433. oscura/visualization/palettes.py +446 -0
  434. oscura/visualization/plot.py +92 -0
  435. oscura/visualization/power.py +290 -0
  436. oscura/visualization/power_extended.py +626 -0
  437. oscura/visualization/presets.py +467 -0
  438. oscura/visualization/protocols.py +932 -0
  439. oscura/visualization/render.py +207 -0
  440. oscura/visualization/rendering.py +444 -0
  441. oscura/visualization/reverse_engineering.py +791 -0
  442. oscura/visualization/signal_integrity.py +808 -0
  443. oscura/visualization/specialized.py +553 -0
  444. oscura/visualization/spectral.py +811 -0
  445. oscura/visualization/styles.py +381 -0
  446. oscura/visualization/thumbnails.py +311 -0
  447. oscura/visualization/time_axis.py +351 -0
  448. oscura/visualization/waveform.py +367 -0
  449. oscura/workflow/__init__.py +13 -0
  450. oscura/workflow/dag.py +377 -0
  451. oscura/workflows/__init__.py +58 -0
  452. oscura/workflows/compliance.py +280 -0
  453. oscura/workflows/digital.py +272 -0
  454. oscura/workflows/multi_trace.py +502 -0
  455. oscura/workflows/power.py +178 -0
  456. oscura/workflows/protocol.py +492 -0
  457. oscura/workflows/reverse_engineering.py +639 -0
  458. oscura/workflows/signal_integrity.py +227 -0
  459. oscura-0.1.1.dist-info/METADATA +300 -0
  460. oscura-0.1.1.dist-info/RECORD +463 -0
  461. oscura-0.1.1.dist-info/entry_points.txt +2 -0
  462. {oscura-0.0.1.dist-info → oscura-0.1.1.dist-info}/licenses/LICENSE +1 -1
  463. oscura-0.0.1.dist-info/METADATA +0 -63
  464. oscura-0.0.1.dist-info/RECORD +0 -5
  465. {oscura-0.0.1.dist-info → oscura-0.1.1.dist-info}/WHEEL +0 -0
oscura/core/audit.py ADDED
@@ -0,0 +1,457 @@
1
+ """Audit trail with HMAC chain verification for compliance and tamper detection.
2
+
3
+ This module provides tamper-evident audit logging using HMAC signatures
4
+ to create a verifiable chain of audit entries.
5
+
6
+
7
+ Example:
8
+ >>> from oscura.core.audit import AuditTrail
9
+ >>> audit = AuditTrail(secret_key=b"my-secret-key")
10
+ >>> audit.record_action("load_trace", {"file": "data.bin"}, user="alice")
11
+ >>> audit.record_action("compute_fft", {"samples": 1000000}, user="alice")
12
+ >>> # Verify integrity
13
+ >>> is_valid = audit.verify_integrity()
14
+ >>> # Export audit log
15
+ >>> audit.export_audit_log("audit.json", format="json")
16
+
17
+ References:
18
+ LOG-009: Comprehensive Audit Trail for Compliance
19
+ HMAC-SHA256 for tamper detection
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import getpass
25
+ import hashlib
26
+ import hmac
27
+ import json
28
+ import os
29
+ import socket
30
+ from dataclasses import asdict, dataclass, field
31
+ from datetime import UTC, datetime
32
+ from pathlib import Path
33
+ from typing import Any, Literal
34
+
35
+ from oscura.core.logging import format_timestamp
36
+
37
+
38
+ @dataclass
39
+ class AuditEntry:
40
+ """Single audit trail entry with HMAC signature.
41
+
42
+ Each entry records an auditable action and is linked to the previous
43
+ entry via HMAC chaining for tamper detection.
44
+
45
+ Attributes:
46
+ timestamp: ISO 8601 timestamp (UTC) of the action.
47
+ action: Action identifier (e.g., "load_trace", "compute_fft").
48
+ details: Additional details about the action (parameters, results).
49
+ user: Username who performed the action (defaults to current user).
50
+ host: Hostname where the action was performed.
51
+ previous_hash: HMAC of the previous entry (for chain verification).
52
+ hmac: HMAC signature of this entry.
53
+
54
+ References:
55
+ LOG-009: Comprehensive Audit Trail for Compliance
56
+ """
57
+
58
+ timestamp: str
59
+ action: str
60
+ details: dict[str, Any]
61
+ user: str
62
+ host: str
63
+ previous_hash: str
64
+ hmac: str = field(default="")
65
+
66
+ def to_dict(self) -> dict[str, Any]:
67
+ """Convert audit entry to dictionary.
68
+
69
+ Returns:
70
+ Dictionary representation of the audit entry.
71
+ """
72
+ return asdict(self)
73
+
74
+ @classmethod
75
+ def from_dict(cls, data: dict[str, Any]) -> AuditEntry:
76
+ """Create audit entry from dictionary.
77
+
78
+ Args:
79
+ data: Dictionary containing audit entry data.
80
+
81
+ Returns:
82
+ AuditEntry instance.
83
+ """
84
+ return cls(**data)
85
+
86
+
87
+ class AuditTrail:
88
+ """Tamper-evident audit trail with HMAC chain verification.
89
+
90
+ Maintains a chain of audit entries where each entry is cryptographically
91
+ linked to the previous entry using HMAC signatures. This allows detection
92
+ of any tampering or modification of the audit log.
93
+
94
+ The HMAC chain works as follows:
95
+ 1. Each entry contains the HMAC of the previous entry
96
+ 2. Each entry's HMAC is computed over: timestamp + action + details + user + previous_hash
97
+ 3. Any modification to any entry breaks the chain and fails verification
98
+
99
+ Args:
100
+ secret_key: Secret key for HMAC computation (required for tamper detection).
101
+ hash_algorithm: Hash algorithm to use (default: 'sha256').
102
+
103
+ Example:
104
+ >>> audit = AuditTrail(secret_key=b"my-secret")
105
+ >>> audit.record_action("operation", {"param": "value"})
106
+ >>> assert audit.verify_integrity()
107
+
108
+ References:
109
+ LOG-009: Comprehensive Audit Trail for Compliance
110
+ """
111
+
112
+ def __init__(
113
+ self,
114
+ secret_key: bytes | None = None,
115
+ hash_algorithm: Literal["sha256", "sha512"] = "sha256",
116
+ ):
117
+ """Initialize audit trail.
118
+
119
+ Args:
120
+ secret_key: Secret key for HMAC computation. If None, a random key is generated.
121
+ hash_algorithm: Hash algorithm to use (sha256 or sha512).
122
+ """
123
+ self._entries: list[AuditEntry] = []
124
+ self._secret_key = secret_key or os.urandom(32)
125
+ self._hash_algorithm = hash_algorithm
126
+
127
+ def record_action(
128
+ self,
129
+ action: str,
130
+ details: dict[str, Any],
131
+ user: str | None = None,
132
+ ) -> AuditEntry:
133
+ """Record an auditable action.
134
+
135
+ Creates a new audit entry with HMAC signature and adds it to the chain.
136
+
137
+ Args:
138
+ action: Action identifier (e.g., "load_trace", "compute_measurement").
139
+ details: Dictionary of action details (parameters, results, etc.).
140
+ user: Username who performed the action (defaults to current user).
141
+
142
+ Returns:
143
+ The created AuditEntry.
144
+
145
+ Example:
146
+ >>> audit = AuditTrail(secret_key=b"key")
147
+ >>> entry = audit.record_action(
148
+ ... "load_trace",
149
+ ... {"file": "data.bin", "size_mb": 100},
150
+ ... user="alice"
151
+ ... )
152
+
153
+ References:
154
+ LOG-009: Comprehensive Audit Trail for Compliance
155
+ """
156
+ # Get current user and host
157
+ if user is None:
158
+ try:
159
+ user = getpass.getuser()
160
+ except Exception:
161
+ user = "unknown"
162
+
163
+ try:
164
+ host = socket.gethostname()
165
+ except Exception:
166
+ host = "unknown"
167
+
168
+ # Get timestamp
169
+ timestamp = format_timestamp(datetime.now(UTC), format="iso8601")
170
+
171
+ # Get previous hash
172
+ previous_hash = self._entries[-1].hmac if self._entries else "GENESIS"
173
+
174
+ # Create entry (without HMAC initially)
175
+ entry = AuditEntry(
176
+ timestamp=timestamp,
177
+ action=action,
178
+ details=details,
179
+ user=user,
180
+ host=host,
181
+ previous_hash=previous_hash,
182
+ hmac="",
183
+ )
184
+
185
+ # Compute HMAC
186
+ entry.hmac = self._compute_hmac(entry)
187
+
188
+ # Add to chain
189
+ self._entries.append(entry)
190
+
191
+ return entry
192
+
193
+ def verify_integrity(self) -> bool:
194
+ """Verify HMAC chain integrity.
195
+
196
+ Verifies that:
197
+ 1. Each entry's HMAC is valid
198
+ 2. Each entry's previous_hash matches the previous entry's HMAC
199
+ 3. No entries have been tampered with or removed
200
+
201
+ Returns:
202
+ True if the audit trail is intact and untampered, False otherwise.
203
+
204
+ Example:
205
+ >>> audit = AuditTrail(secret_key=b"key")
206
+ >>> audit.record_action("action1", {})
207
+ >>> audit.record_action("action2", {})
208
+ >>> assert audit.verify_integrity() # Should be True
209
+ >>> # Tampering with an entry would break the chain
210
+ >>> audit._entries[0].action = "modified"
211
+ >>> assert not audit.verify_integrity() # Should be False
212
+
213
+ References:
214
+ LOG-009: Comprehensive Audit Trail for Compliance
215
+ """
216
+ if not self._entries:
217
+ return True # Empty trail is valid
218
+
219
+ for i, entry in enumerate(self._entries):
220
+ # Verify HMAC
221
+ expected_hmac = self._compute_hmac(entry)
222
+ if entry.hmac != expected_hmac:
223
+ return False
224
+
225
+ # Verify previous hash linkage
226
+ if i == 0:
227
+ if entry.previous_hash != "GENESIS":
228
+ return False
229
+ elif entry.previous_hash != self._entries[i - 1].hmac:
230
+ return False
231
+
232
+ return True
233
+
234
+ def export_audit_log(
235
+ self,
236
+ path: str,
237
+ format: Literal["json", "csv"] = "json",
238
+ ) -> None:
239
+ """Export audit trail to file.
240
+
241
+ Args:
242
+ path: Path to export file.
243
+ format: Export format (json or csv).
244
+
245
+ Raises:
246
+ ValueError: If format is not supported.
247
+
248
+ Example:
249
+ >>> audit = AuditTrail(secret_key=b"key")
250
+ >>> audit.record_action("test", {})
251
+ >>> audit.export_audit_log("audit.json", format="json")
252
+
253
+ References:
254
+ LOG-009: Comprehensive Audit Trail for Compliance
255
+ """
256
+ path_obj = Path(path)
257
+ path_obj.parent.mkdir(parents=True, exist_ok=True)
258
+
259
+ if format == "json":
260
+ self._export_json(path_obj)
261
+ elif format == "csv":
262
+ self._export_csv(path_obj)
263
+ else:
264
+ raise ValueError(f"Unsupported format: {format}")
265
+
266
+ def get_entries(
267
+ self,
268
+ since: datetime | None = None,
269
+ action_type: str | None = None,
270
+ ) -> list[AuditEntry]:
271
+ """Query audit entries with optional filtering.
272
+
273
+ Args:
274
+ since: Return only entries after this datetime (UTC).
275
+ action_type: Return only entries with this action type.
276
+
277
+ Returns:
278
+ List of matching AuditEntry objects.
279
+
280
+ Example:
281
+ >>> from datetime import datetime, UTC, timedelta
282
+ >>> audit = AuditTrail(secret_key=b"key")
283
+ >>> audit.record_action("load", {})
284
+ >>> audit.record_action("analyze", {})
285
+ >>> # Get all load actions
286
+ >>> loads = audit.get_entries(action_type="load")
287
+ >>> # Get entries from last hour
288
+ >>> recent = audit.get_entries(since=datetime.now(UTC) - timedelta(hours=1))
289
+
290
+ References:
291
+ LOG-009: Comprehensive Audit Trail for Compliance
292
+ """
293
+ results = self._entries.copy()
294
+
295
+ # Filter by timestamp
296
+ if since is not None:
297
+ since_str = format_timestamp(since, format="iso8601")
298
+ results = [e for e in results if e.timestamp >= since_str]
299
+
300
+ # Filter by action type
301
+ if action_type is not None:
302
+ results = [e for e in results if e.action == action_type]
303
+
304
+ return results
305
+
306
+ def _compute_hmac(self, entry: AuditEntry) -> str:
307
+ """Compute HMAC signature for an audit entry.
308
+
309
+ Args:
310
+ entry: Audit entry to sign.
311
+
312
+ Returns:
313
+ Hexadecimal HMAC signature.
314
+
315
+ Raises:
316
+ ValueError: If hash algorithm is unsupported.
317
+
318
+ References:
319
+ LOG-009: HMAC-based tamper detection
320
+ """
321
+ # Create canonical representation
322
+ canonical = (
323
+ f"{entry.timestamp}|{entry.action}|{json.dumps(entry.details, sort_keys=True)}"
324
+ f"|{entry.user}|{entry.host}|{entry.previous_hash}"
325
+ )
326
+
327
+ # Compute HMAC
328
+ if self._hash_algorithm == "sha256":
329
+ h = hmac.new(self._secret_key, canonical.encode("utf-8"), hashlib.sha256)
330
+ elif self._hash_algorithm == "sha512":
331
+ h = hmac.new(self._secret_key, canonical.encode("utf-8"), hashlib.sha512)
332
+ else:
333
+ raise ValueError(f"Unsupported hash algorithm: {self._hash_algorithm}")
334
+
335
+ return h.hexdigest()
336
+
337
+ def _export_json(self, path: Path) -> None:
338
+ """Export audit trail as JSON.
339
+
340
+ Args:
341
+ path: Path to JSON file.
342
+ """
343
+ data = {
344
+ "version": "1.0",
345
+ "hash_algorithm": self._hash_algorithm,
346
+ "entries": [entry.to_dict() for entry in self._entries],
347
+ }
348
+
349
+ with open(path, "w", encoding="utf-8") as f:
350
+ json.dump(data, f, indent=2)
351
+
352
+ def _export_csv(self, path: Path) -> None:
353
+ """Export audit trail as CSV.
354
+
355
+ Args:
356
+ path: Path to CSV file.
357
+ """
358
+ import csv
359
+
360
+ with open(path, "w", newline="", encoding="utf-8") as f:
361
+ if not self._entries:
362
+ return
363
+
364
+ # Get all possible detail keys
365
+ detail_keys = set() # type: ignore[var-annotated]
366
+ for entry in self._entries:
367
+ detail_keys.update(entry.details.keys())
368
+ detail_keys = sorted(detail_keys) # type: ignore[assignment]
369
+
370
+ # Create CSV writer
371
+ fieldnames = [
372
+ "timestamp",
373
+ "action",
374
+ "user",
375
+ "host",
376
+ "previous_hash",
377
+ "hmac",
378
+ ] + [f"detail_{k}" for k in detail_keys]
379
+
380
+ writer = csv.DictWriter(f, fieldnames=fieldnames)
381
+ writer.writeheader()
382
+
383
+ # Write entries
384
+ for entry in self._entries:
385
+ row = {
386
+ "timestamp": entry.timestamp,
387
+ "action": entry.action,
388
+ "user": entry.user,
389
+ "host": entry.host,
390
+ "previous_hash": entry.previous_hash,
391
+ "hmac": entry.hmac,
392
+ }
393
+ # Add details
394
+ for key in detail_keys:
395
+ value = entry.details.get(key)
396
+ row[f"detail_{key}"] = json.dumps(value) if value is not None else ""
397
+
398
+ writer.writerow(row)
399
+
400
+
401
+ # Convenience function for global audit trail
402
+ _global_audit_trail: AuditTrail | None = None
403
+
404
+
405
+ def get_global_audit_trail(secret_key: bytes | None = None) -> AuditTrail:
406
+ """Get or create the global audit trail.
407
+
408
+ Args:
409
+ secret_key: Secret key for HMAC computation (only used on first call).
410
+
411
+ Returns:
412
+ Global AuditTrail instance.
413
+
414
+ Example:
415
+ >>> from oscura.core.audit import get_global_audit_trail
416
+ >>> audit = get_global_audit_trail(secret_key=b"my-key")
417
+ >>> audit.record_action("test", {})
418
+
419
+ References:
420
+ LOG-009: Comprehensive Audit Trail for Compliance
421
+ """
422
+ global _global_audit_trail
423
+ if _global_audit_trail is None:
424
+ _global_audit_trail = AuditTrail(secret_key=secret_key)
425
+ return _global_audit_trail
426
+
427
+
428
+ def record_audit(action: str, details: dict[str, Any], user: str | None = None) -> AuditEntry:
429
+ """Record an action to the global audit trail.
430
+
431
+ Convenience function for recording to the global audit trail.
432
+
433
+ Args:
434
+ action: Action identifier.
435
+ details: Action details.
436
+ user: Username (defaults to current user).
437
+
438
+ Returns:
439
+ Created AuditEntry.
440
+
441
+ Example:
442
+ >>> from oscura.core.audit import record_audit
443
+ >>> record_audit("compute_fft", {"samples": 1000000})
444
+
445
+ References:
446
+ LOG-009: Comprehensive Audit Trail for Compliance
447
+ """
448
+ audit = get_global_audit_trail()
449
+ return audit.record_action(action, details, user)
450
+
451
+
452
+ __all__ = [
453
+ "AuditEntry",
454
+ "AuditTrail",
455
+ "get_global_audit_trail",
456
+ "record_audit",
457
+ ]