threatwright 0.1.0__tar.gz

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 (244) hide show
  1. threatwright-0.1.0/.dockerignore +19 -0
  2. threatwright-0.1.0/.gitattributes +6 -0
  3. threatwright-0.1.0/.github/workflows/audit.yml +52 -0
  4. threatwright-0.1.0/.github/workflows/ci.yml +58 -0
  5. threatwright-0.1.0/.github/workflows/leakcheck.yml +26 -0
  6. threatwright-0.1.0/.github/workflows/release.yml +187 -0
  7. threatwright-0.1.0/.gitignore +72 -0
  8. threatwright-0.1.0/.pre-commit-config.yaml +13 -0
  9. threatwright-0.1.0/.pre-commit-hooks.yaml +9 -0
  10. threatwright-0.1.0/Dockerfile +37 -0
  11. threatwright-0.1.0/LICENSE +661 -0
  12. threatwright-0.1.0/PKG-INFO +201 -0
  13. threatwright-0.1.0/README.md +183 -0
  14. threatwright-0.1.0/ROADMAP.md +23 -0
  15. threatwright-0.1.0/SECURITY.md +70 -0
  16. threatwright-0.1.0/app/index.html +12 -0
  17. threatwright-0.1.0/app/package-lock.json +1462 -0
  18. threatwright-0.1.0/app/package.json +24 -0
  19. threatwright-0.1.0/app/src/App.svelte +372 -0
  20. threatwright-0.1.0/app/src/api.ts +61 -0
  21. threatwright-0.1.0/app/src/app.css +151 -0
  22. threatwright-0.1.0/app/src/branding.ts +2 -0
  23. threatwright-0.1.0/app/src/fields.ts +150 -0
  24. threatwright-0.1.0/app/src/glossary.ts +220 -0
  25. threatwright-0.1.0/app/src/i18n.ts +448 -0
  26. threatwright-0.1.0/app/src/lib/Assessment.svelte +153 -0
  27. threatwright-0.1.0/app/src/lib/Assistant.svelte +163 -0
  28. threatwright-0.1.0/app/src/lib/Catalogs.svelte +78 -0
  29. threatwright-0.1.0/app/src/lib/Controls.svelte +92 -0
  30. threatwright-0.1.0/app/src/lib/Coverage.svelte +147 -0
  31. threatwright-0.1.0/app/src/lib/CustomField.svelte +36 -0
  32. threatwright-0.1.0/app/src/lib/CyberCauseDialog.svelte +88 -0
  33. threatwright-0.1.0/app/src/lib/Documents.svelte +153 -0
  34. threatwright-0.1.0/app/src/lib/Info.svelte +67 -0
  35. threatwright-0.1.0/app/src/lib/MeasureBoard.svelte +76 -0
  36. threatwright-0.1.0/app/src/lib/ModelMeta.svelte +125 -0
  37. threatwright-0.1.0/app/src/lib/MultiSelect.svelte +69 -0
  38. threatwright-0.1.0/app/src/lib/ObjectForm.svelte +266 -0
  39. threatwright-0.1.0/app/src/lib/Objects.svelte +148 -0
  40. threatwright-0.1.0/app/src/lib/Overview.svelte +159 -0
  41. threatwright-0.1.0/app/src/lib/RiskBadge.svelte +14 -0
  42. threatwright-0.1.0/app/src/lib/Settings.svelte +119 -0
  43. threatwright-0.1.0/app/src/lib/Setup.svelte +811 -0
  44. threatwright-0.1.0/app/src/lib/Start.svelte +155 -0
  45. threatwright-0.1.0/app/src/lib/Validation.svelte +108 -0
  46. threatwright-0.1.0/app/src/lib/diagram/Canvas.svelte +298 -0
  47. threatwright-0.1.0/app/src/lib/diagram/Diagram.svelte +165 -0
  48. threatwright-0.1.0/app/src/lib/diagram/ElementNode.svelte +108 -0
  49. threatwright-0.1.0/app/src/lib/diagram/Legend.svelte +82 -0
  50. threatwright-0.1.0/app/src/lib/diagram/ZoneNode.svelte +24 -0
  51. threatwright-0.1.0/app/src/lib/icons.ts +75 -0
  52. threatwright-0.1.0/app/src/main.ts +5 -0
  53. threatwright-0.1.0/app/src/rule-text.ts +74 -0
  54. threatwright-0.1.0/app/src/setup-text.ts +361 -0
  55. threatwright-0.1.0/app/src/state.svelte.ts +162 -0
  56. threatwright-0.1.0/app/src/types.ts +118 -0
  57. threatwright-0.1.0/app/svelte.config.js +3 -0
  58. threatwright-0.1.0/app/tsconfig.json +13 -0
  59. threatwright-0.1.0/app/vite.config.ts +14 -0
  60. threatwright-0.1.0/ci/github-actions.yml +92 -0
  61. threatwright-0.1.0/ci/gitlab-ci.yml +66 -0
  62. threatwright-0.1.0/docs/VERIFY.md +38 -0
  63. threatwright-0.1.0/docs/adr/0001-record-architecture-decisions.md +12 -0
  64. threatwright-0.1.0/docs/adr/0002-licensing.md +20 -0
  65. threatwright-0.1.0/docs/adr/0003-architecture-and-ui.md +21 -0
  66. threatwright-0.1.0/docs/adr/0004-storage-format.md +21 -0
  67. threatwright-0.1.0/docs/adr/0005-methodology-as-configuration.md +15 -0
  68. threatwright-0.1.0/docs/adr/0006-oscal-import-only.md +17 -0
  69. threatwright-0.1.0/docs/adr/0007-local-first-no-network.md +14 -0
  70. threatwright-0.1.0/docs/adr/0008-public-repo-hygiene.md +19 -0
  71. threatwright-0.1.0/docs/adr/0009-ci-integration-gitlab.md +18 -0
  72. threatwright-0.1.0/docs/adr/0010-tr-method-interpretation.md +20 -0
  73. threatwright-0.1.0/docs/adr/0011-library-format.md +18 -0
  74. threatwright-0.1.0/docs/adr/0012-oscal-version-and-arc.md +43 -0
  75. threatwright-0.1.0/docs/adr/0013-self-hosted-gui.md +18 -0
  76. threatwright-0.1.0/docs/bibliotheksformat.md +110 -0
  77. threatwright-0.1.0/docs/ci.md +86 -0
  78. threatwright-0.1.0/docs/cra-self-assessment.md +66 -0
  79. threatwright-0.1.0/docs/faq-cyberrisiko.md +33 -0
  80. threatwright-0.1.0/docs/git-arbeitsweise.md +174 -0
  81. threatwright-0.1.0/docs/methodik.md +64 -0
  82. threatwright-0.1.0/docs/oscal.md +141 -0
  83. threatwright-0.1.0/docs/pruefregeln.md +52 -0
  84. threatwright-0.1.0/docs/schnellstart.md +58 -0
  85. threatwright-0.1.0/docs/security.txt +13 -0
  86. threatwright-0.1.0/docs/tutorial.md +86 -0
  87. threatwright-0.1.0/docs/vorlagenreferenz.md +299 -0
  88. threatwright-0.1.0/packaging/build.py +55 -0
  89. threatwright-0.1.0/packaging/threatwright.spec +34 -0
  90. threatwright-0.1.0/pyproject.toml +59 -0
  91. threatwright-0.1.0/schemas/asset.v1.schema.json +166 -0
  92. threatwright-0.1.0/schemas/custom-fields.v1.schema.json +104 -0
  93. threatwright-0.1.0/schemas/diagram-layout.v1.schema.json +69 -0
  94. threatwright-0.1.0/schemas/element.v1.schema.json +124 -0
  95. threatwright-0.1.0/schemas/flow.v1.schema.json +139 -0
  96. threatwright-0.1.0/schemas/measure.v1.schema.json +207 -0
  97. threatwright-0.1.0/schemas/model.v1.schema.json +226 -0
  98. threatwright-0.1.0/schemas/project.v1.schema.json +66 -0
  99. threatwright-0.1.0/schemas/question.v1.schema.json +117 -0
  100. threatwright-0.1.0/schemas/threat.v1.schema.json +342 -0
  101. threatwright-0.1.0/scripts/check_forbidden_files.py +40 -0
  102. threatwright-0.1.0/scripts/library_coverage.py +44 -0
  103. threatwright-0.1.0/scripts/make_templates.py +229 -0
  104. threatwright-0.1.0/src/threatwright/__init__.py +3 -0
  105. threatwright-0.1.0/src/threatwright/__main__.py +3 -0
  106. threatwright-0.1.0/src/threatwright/arc.py +295 -0
  107. threatwright-0.1.0/src/threatwright/assistant.py +290 -0
  108. threatwright-0.1.0/src/threatwright/branding.py +4 -0
  109. threatwright-0.1.0/src/threatwright/catalogs/attack-ics.yaml +87 -0
  110. threatwright-0.1.0/src/threatwright/catalogs/cra.yaml +107 -0
  111. threatwright-0.1.0/src/threatwright/catalogs/emb3d.yaml +90 -0
  112. threatwright-0.1.0/src/threatwright/catalogs/iec62443.yaml +16 -0
  113. threatwright-0.1.0/src/threatwright/ci.py +158 -0
  114. threatwright-0.1.0/src/threatwright/ci_templates/github-actions.yml.j2 +95 -0
  115. threatwright-0.1.0/src/threatwright/ci_templates/gitlab-ci.yml.j2 +69 -0
  116. threatwright-0.1.0/src/threatwright/cli.py +370 -0
  117. threatwright-0.1.0/src/threatwright/diagram.py +110 -0
  118. threatwright-0.1.0/src/threatwright/interop/__init__.py +11 -0
  119. threatwright-0.1.0/src/threatwright/interop/export.py +196 -0
  120. threatwright-0.1.0/src/threatwright/interop/importers.py +411 -0
  121. threatwright-0.1.0/src/threatwright/libraries/ot/elements.yaml +501 -0
  122. threatwright-0.1.0/src/threatwright/libraries/ot/library.yaml +19 -0
  123. threatwright-0.1.0/src/threatwright/libraries/ot/measures/data.yaml +170 -0
  124. threatwright-0.1.0/src/threatwright/libraries/ot/measures/identity.yaml +468 -0
  125. threatwright-0.1.0/src/threatwright/libraries/ot/measures/integrity.yaml +694 -0
  126. threatwright-0.1.0/src/threatwright/libraries/ot/measures/logging.yaml +114 -0
  127. threatwright-0.1.0/src/threatwright/libraries/ot/measures/network.yaml +361 -0
  128. threatwright-0.1.0/src/threatwright/libraries/ot/measures/organisational.yaml +328 -0
  129. threatwright-0.1.0/src/threatwright/libraries/ot/measures/remote.yaml +281 -0
  130. threatwright-0.1.0/src/threatwright/libraries/ot/measures/safety.yaml +148 -0
  131. threatwright-0.1.0/src/threatwright/libraries/ot/measures/supply-chain.yaml +167 -0
  132. threatwright-0.1.0/src/threatwright/libraries/ot/threats/field.yaml +1461 -0
  133. threatwright-0.1.0/src/threatwright/libraries/ot/threats/host.yaml +1568 -0
  134. threatwright-0.1.0/src/threatwright/libraries/ot/threats/network.yaml +1434 -0
  135. threatwright-0.1.0/src/threatwright/library.py +296 -0
  136. threatwright-0.1.0/src/threatwright/method.py +296 -0
  137. threatwright-0.1.0/src/threatwright/methods/tr-03183-1/method.yaml +223 -0
  138. threatwright-0.1.0/src/threatwright/model/__init__.py +0 -0
  139. threatwright-0.1.0/src/threatwright/model/objects.py +246 -0
  140. threatwright-0.1.0/src/threatwright/model/refactor.py +54 -0
  141. threatwright-0.1.0/src/threatwright/model/schema.py +31 -0
  142. threatwright-0.1.0/src/threatwright/model/store.py +326 -0
  143. threatwright-0.1.0/src/threatwright/oscal/__init__.py +19 -0
  144. threatwright-0.1.0/src/threatwright/oscal/imports.py +393 -0
  145. threatwright-0.1.0/src/threatwright/oscal/project.py +22 -0
  146. threatwright-0.1.0/src/threatwright/oscal/schemas/1.2.3/README.md +32 -0
  147. threatwright-0.1.0/src/threatwright/oscal/schemas/1.2.3/oscal_catalog_schema.json +1295 -0
  148. threatwright-0.1.0/src/threatwright/oscal/schemas/1.2.3/oscal_complete_schema.json +6022 -0
  149. threatwright-0.1.0/src/threatwright/oscal/schemas/1.2.3/oscal_component_schema.json +1821 -0
  150. threatwright-0.1.0/src/threatwright/oscal/schemas/1.2.3/oscal_profile_schema.json +1616 -0
  151. threatwright-0.1.0/src/threatwright/oscal/validate.py +150 -0
  152. threatwright-0.1.0/src/threatwright/render/__init__.py +30 -0
  153. threatwright-0.1.0/src/threatwright/render/build.py +316 -0
  154. threatwright-0.1.0/src/threatwright/render/context.py +579 -0
  155. threatwright-0.1.0/src/threatwright/render/env.py +89 -0
  156. threatwright-0.1.0/src/threatwright/render/labels.py +247 -0
  157. threatwright-0.1.0/src/threatwright/render/odt.py +296 -0
  158. threatwright-0.1.0/src/threatwright/render/package.py +217 -0
  159. threatwright-0.1.0/src/threatwright/render/pdf.py +66 -0
  160. threatwright-0.1.0/src/threatwright/render/sections.py +475 -0
  161. threatwright-0.1.0/src/threatwright/render/word.py +162 -0
  162. threatwright-0.1.0/src/threatwright/report.py +96 -0
  163. threatwright-0.1.0/src/threatwright/rules.py +382 -0
  164. threatwright-0.1.0/src/threatwright/scaffold.py +71 -0
  165. threatwright-0.1.0/src/threatwright/server.py +940 -0
  166. threatwright-0.1.0/src/threatwright/templates/_shared/document.html.j2 +69 -0
  167. threatwright-0.1.0/src/threatwright/templates/_shared/document.md.j2 +47 -0
  168. threatwright-0.1.0/src/threatwright/templates/acceptance-criteria/template.docx +0 -0
  169. threatwright-0.1.0/src/threatwright/templates/acceptance-criteria/template.md +2 -0
  170. threatwright-0.1.0/src/threatwright/templates/acceptance-criteria/template.odt +0 -0
  171. threatwright-0.1.0/src/threatwright/templates/acceptance-criteria/template.yaml +41 -0
  172. threatwright-0.1.0/src/threatwright/templates/tr-analysis/template.docx +0 -0
  173. threatwright-0.1.0/src/threatwright/templates/tr-analysis/template.html +2 -0
  174. threatwright-0.1.0/src/threatwright/templates/tr-analysis/template.md +2 -0
  175. threatwright-0.1.0/src/threatwright/templates/tr-analysis/template.odt +0 -0
  176. threatwright-0.1.0/src/threatwright/templates/tr-analysis/template.yaml +29 -0
  177. threatwright-0.1.0/src/threatwright/templates/tr-analysis-compact/template.docx +0 -0
  178. threatwright-0.1.0/src/threatwright/templates/tr-analysis-compact/template.yaml +47 -0
  179. threatwright-0.1.0/src/threatwright/vcs.py +349 -0
  180. threatwright-0.1.0/src/threatwright/web/assets/elk.bundled-B7GIUaPm.js +24 -0
  181. threatwright-0.1.0/src/threatwright/web/assets/index-CQEumOmL.css +1 -0
  182. threatwright-0.1.0/src/threatwright/web/assets/index-CQtGvHdl.js +13 -0
  183. threatwright-0.1.0/src/threatwright/web/index.html +13 -0
  184. threatwright-0.1.0/tests/conftest.py +135 -0
  185. threatwright-0.1.0/tests/e2e/test_a11y.py +51 -0
  186. threatwright-0.1.0/tests/e2e/test_diagram.py +67 -0
  187. threatwright-0.1.0/tests/e2e/test_diagram_zones.py +49 -0
  188. threatwright-0.1.0/tests/e2e/test_documents.py +22 -0
  189. threatwright-0.1.0/tests/e2e/test_gui.py +41 -0
  190. threatwright-0.1.0/tests/e2e/test_info.py +14 -0
  191. threatwright-0.1.0/tests/e2e/test_landing.py +27 -0
  192. threatwright-0.1.0/tests/e2e/test_language.py +16 -0
  193. threatwright-0.1.0/tests/e2e/test_setup.py +90 -0
  194. threatwright-0.1.0/tests/fixtures/broken/custom-fields.yaml +8 -0
  195. threatwright-0.1.0/tests/fixtures/broken/method-overrides.yaml +3 -0
  196. threatwright-0.1.0/tests/fixtures/broken/models/m/assets/A-0001.yaml +5 -0
  197. threatwright-0.1.0/tests/fixtures/broken/models/m/assets/A-0002.yaml +6 -0
  198. threatwright-0.1.0/tests/fixtures/broken/models/m/elements/E-0001.yaml +8 -0
  199. threatwright-0.1.0/tests/fixtures/broken/models/m/flows/F-0001.yaml +6 -0
  200. threatwright-0.1.0/tests/fixtures/broken/models/m/measures/M-0001.yaml +4 -0
  201. threatwright-0.1.0/tests/fixtures/broken/models/m/measures/M-0002.yaml +4 -0
  202. threatwright-0.1.0/tests/fixtures/broken/models/m/model.yaml +9 -0
  203. threatwright-0.1.0/tests/fixtures/broken/models/m/questions/Q-0001.yaml +4 -0
  204. threatwright-0.1.0/tests/fixtures/broken/models/m/threats/T-0001.yaml +8 -0
  205. threatwright-0.1.0/tests/fixtures/broken/models/m/threats/T-0002.yaml +11 -0
  206. threatwright-0.1.0/tests/fixtures/broken/models/m/threats/T-0003.yaml +9 -0
  207. threatwright-0.1.0/tests/fixtures/broken/models/m/threats/T-0004.yaml +9 -0
  208. threatwright-0.1.0/tests/fixtures/broken/models/m/threats/T-0005.yaml +4 -0
  209. threatwright-0.1.0/tests/fixtures/broken/threatwright.yaml +3 -0
  210. threatwright-0.1.0/tests/fixtures/interop/threat-dragon-v2.json +187 -0
  211. threatwright-0.1.0/tests/fixtures/oscal/NOTICE +29 -0
  212. threatwright-0.1.0/tests/fixtures/oscal/grundschutz-excerpt.json +423 -0
  213. threatwright-0.1.0/tests/fixtures/oscal/synthetic-arc-catalog.json +173 -0
  214. threatwright-0.1.0/tests/fixtures/oscal/synthetic-component.json +51 -0
  215. threatwright-0.1.0/tests/fixtures/oscal/synthetic-profile.json +38 -0
  216. threatwright-0.1.0/tests/fixtures/project/models/main/assets/A-0001.yaml +5 -0
  217. threatwright-0.1.0/tests/fixtures/project/models/main/assets/A-0002.yaml +5 -0
  218. threatwright-0.1.0/tests/fixtures/project/models/main/diagram.layout.yaml +5 -0
  219. threatwright-0.1.0/tests/fixtures/project/models/main/elements/E-0001.yaml +7 -0
  220. threatwright-0.1.0/tests/fixtures/project/models/main/elements/E-0002.yaml +7 -0
  221. threatwright-0.1.0/tests/fixtures/project/models/main/elements/E-0003.yaml +10 -0
  222. threatwright-0.1.0/tests/fixtures/project/models/main/flows/F-0001.yaml +9 -0
  223. threatwright-0.1.0/tests/fixtures/project/models/main/measures/M-0001.yaml +8 -0
  224. threatwright-0.1.0/tests/fixtures/project/models/main/model.yaml +26 -0
  225. threatwright-0.1.0/tests/fixtures/project/models/main/questions/Q-0001.yaml +5 -0
  226. threatwright-0.1.0/tests/fixtures/project/models/main/threats/T-0001.yaml +24 -0
  227. threatwright-0.1.0/tests/fixtures/project/threatwright.yaml +5 -0
  228. threatwright-0.1.0/tests/test_arc.py +127 -0
  229. threatwright-0.1.0/tests/test_assistant.py +128 -0
  230. threatwright-0.1.0/tests/test_ci.py +83 -0
  231. threatwright-0.1.0/tests/test_cli_tools.py +98 -0
  232. threatwright-0.1.0/tests/test_interop.py +190 -0
  233. threatwright-0.1.0/tests/test_library.py +85 -0
  234. threatwright-0.1.0/tests/test_method.py +164 -0
  235. threatwright-0.1.0/tests/test_oscal.py +309 -0
  236. threatwright-0.1.0/tests/test_oscal_wiring.py +70 -0
  237. threatwright-0.1.0/tests/test_refactor.py +49 -0
  238. threatwright-0.1.0/tests/test_render.py +375 -0
  239. threatwright-0.1.0/tests/test_rule_text.py +18 -0
  240. threatwright-0.1.0/tests/test_rules.py +83 -0
  241. threatwright-0.1.0/tests/test_server.py +174 -0
  242. threatwright-0.1.0/tests/test_store.py +141 -0
  243. threatwright-0.1.0/tests/test_vcs.py +149 -0
  244. threatwright-0.1.0/uv.lock +1391 -0
@@ -0,0 +1,19 @@
1
+ .git
2
+ **/node_modules
3
+ .venv
4
+ build
5
+ dist
6
+ .claude
7
+ .private
8
+ .env
9
+ .env.*
10
+ *.pem
11
+ *.key
12
+ *.p12
13
+ *.pfx
14
+ secrets
15
+ **/__pycache__
16
+ .mypy_cache
17
+ .ruff_cache
18
+ .pytest_cache
19
+ src/threatwright/web
@@ -0,0 +1,6 @@
1
+ * text=auto eol=lf
2
+ *.docx binary
3
+ *.odt binary
4
+ *.xlsx binary
5
+ *.png binary
6
+ *.ico binary
@@ -0,0 +1,52 @@
1
+ name: audit
2
+
3
+ # Known vulnerabilities in locked dependencies (SECURITY.md, docs/cra-self-assessment.md).
4
+
5
+ on:
6
+ pull_request:
7
+ schedule:
8
+ - cron: "17 5 * * 1" # weekly, Monday
9
+ workflow_dispatch:
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ python:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
19
+ with:
20
+ persist-credentials: false
21
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
22
+ - name: pip-audit (runtime dependencies from uv.lock)
23
+ run: |
24
+ uv export --frozen --no-dev --no-emit-project --format requirements-txt -o requirements.txt
25
+ uvx pip-audit==2.10.1 --disable-pip --require-hashes -r requirements.txt
26
+
27
+ npm:
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
31
+ with:
32
+ persist-credentials: false
33
+ - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
34
+ with:
35
+ node-version: "24"
36
+ - name: npm audit (app/package-lock.json)
37
+ working-directory: app
38
+ run: npm audit --audit-level=moderate
39
+
40
+ osv:
41
+ # Second opinion over both lockfiles; informative only.
42
+ runs-on: ubuntu-latest
43
+ continue-on-error: true
44
+ steps:
45
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
46
+ with:
47
+ persist-credentials: false
48
+ - uses: google/osv-scanner-action/osv-scanner-action@b1d267aea5211fa648d9d442fa64b90dbdcbdd36 # v2.7.0
49
+ with:
50
+ scan-args: |-
51
+ --lockfile=uv.lock
52
+ --lockfile=app/package-lock.json
@@ -0,0 +1,58 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ test:
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ os: [ubuntu-latest, windows-latest]
17
+ python: ["3.12", "3.14"]
18
+ runs-on: ${{ matrix.os }}
19
+ steps:
20
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
21
+ with:
22
+ persist-credentials: false
23
+
24
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
25
+ with:
26
+ python-version: ${{ matrix.python }}
27
+
28
+ - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
29
+ with:
30
+ node-version: "24"
31
+
32
+ - name: Frontend check and build
33
+ working-directory: app
34
+ run: |
35
+ npm ci --no-audit --no-fund
36
+ npm run check
37
+ npm run build
38
+
39
+ - run: uv sync --locked
40
+ - run: uv run ruff check .
41
+ - run: uv run ruff format --check .
42
+ - run: uv run mypy
43
+ - run: uv run playwright install --with-deps chromium
44
+ - run: uv run pytest -q
45
+ - run: uv run threatwright validate tests/fixtures/project
46
+
47
+ - name: Fixture project survives a load/save roundtrip without diff
48
+ run: |
49
+ uv run python -c "from threatwright.model.store import Project; p = Project.load('tests/fixtures/project'); assert not p.issues, p.issues; p.save()"
50
+ git diff --exit-code
51
+
52
+ # One stable check name for branch protection; matrix job names change with the matrix.
53
+ ci-ok:
54
+ if: always()
55
+ needs: [test]
56
+ runs-on: ubuntu-latest
57
+ steps:
58
+ - run: test "${{ needs.test.result }}" = success
@@ -0,0 +1,26 @@
1
+ name: leakcheck
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ leakcheck:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
16
+ with:
17
+ fetch-depth: 0 # scan full history, not just HEAD
18
+ persist-credentials: false
19
+
20
+ - name: Forbidden files (AI tooling, local config, secrets)
21
+ run: python3 scripts/check_forbidden_files.py
22
+
23
+ - name: Secret scan (gitleaks, full history)
24
+ run: >
25
+ docker run --rm -v "$PWD:/repo" ghcr.io/gitleaks/gitleaks:v8.30.1
26
+ git /repo --redact --verbose --exit-code 1
@@ -0,0 +1,187 @@
1
+ name: release
2
+
3
+ # Tag vX.Y.Z (must match the version in pyproject.toml) -> GitHub Release with sdist, wheel,
4
+ # portable builds (Windows zip, Linux tar.gz), CycloneDX SBOMs, SHA256SUMS, Sigstore
5
+ # provenance; PyPI via trusted publishing; container image on ghcr.io.
6
+
7
+ on:
8
+ push:
9
+ tags: ["v*"]
10
+
11
+ permissions: {}
12
+
13
+ jobs:
14
+ frontend:
15
+ runs-on: ubuntu-latest
16
+ permissions:
17
+ contents: read
18
+ steps:
19
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
20
+ with:
21
+ persist-credentials: false
22
+ - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
23
+ with:
24
+ node-version: "24"
25
+ - name: Build bundle and npm SBOM
26
+ working-directory: app
27
+ run: |
28
+ npm ci --no-audit --no-fund
29
+ npm run build
30
+ # The bundle is compiled from devDependencies, so the SBOM includes them.
31
+ npm sbom --sbom-format cyclonedx > ../sbom-npm.cdx.json
32
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
33
+ with:
34
+ name: web
35
+ path: src/threatwright/web/
36
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
37
+ with:
38
+ name: release-sbom-npm
39
+ path: sbom-npm.cdx.json
40
+
41
+ python:
42
+ needs: frontend
43
+ runs-on: ubuntu-latest
44
+ permissions:
45
+ contents: read
46
+ steps:
47
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
48
+ with:
49
+ persist-credentials: false
50
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
51
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
52
+ with:
53
+ name: web
54
+ path: src/threatwright/web
55
+ - name: Tag matches package version
56
+ run: test "$(uv version --short)" = "${GITHUB_REF_NAME#v}"
57
+ - run: uv build
58
+ - name: Python SBOM (runtime dependencies from uv.lock)
59
+ run: |
60
+ uv export --frozen --no-dev --no-emit-project --format requirements-txt -o requirements.txt
61
+ uvx --from cyclonedx-bom==7.5.0 cyclonedx-py requirements requirements.txt -o sbom-python.cdx.json
62
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
63
+ with:
64
+ name: release-python
65
+ path: dist/
66
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
67
+ with:
68
+ name: release-sbom-python
69
+ path: sbom-python.cdx.json
70
+
71
+ portable:
72
+ needs: frontend
73
+ strategy:
74
+ matrix:
75
+ # Linux pinned: the bundle needs at least the build system's glibc, so build on an
76
+ # older base to run on older plant PCs (ubuntu-latest moves to 26.04 from 2026-10-19)
77
+ os: [windows-latest, ubuntu-24.04]
78
+ runs-on: ${{ matrix.os }}
79
+ permissions:
80
+ contents: read
81
+ defaults:
82
+ run:
83
+ shell: bash
84
+ steps:
85
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
86
+ with:
87
+ persist-credentials: false
88
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
89
+ with:
90
+ python-version: "3.13"
91
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
92
+ with:
93
+ name: web
94
+ path: src/threatwright/web
95
+ - run: uv sync --locked
96
+ - run: uv run python packaging/build.py
97
+ - name: Smoke test
98
+ run: |
99
+ ./dist/threatwright/threatwright --version
100
+ ./dist/threatwright/threatwright validate tests/fixtures/project
101
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
102
+ with:
103
+ name: release-portable-${{ matrix.os }}
104
+ path: |
105
+ dist/threatwright-*.zip
106
+ dist/threatwright-*.tar.gz
107
+
108
+ release:
109
+ needs: [frontend, python, portable]
110
+ runs-on: ubuntu-latest
111
+ permissions:
112
+ contents: write # create the release
113
+ id-token: write # Sigstore signing via GitHub OIDC
114
+ attestations: write
115
+ steps:
116
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
117
+ with:
118
+ pattern: release-*
119
+ path: assets
120
+ merge-multiple: true
121
+ - name: Checksums
122
+ working-directory: assets
123
+ run: sha256sum -- * > SHA256SUMS
124
+ - uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
125
+ with:
126
+ subject-path: assets/*
127
+ - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
128
+ - name: Sign checksums (keyless)
129
+ working-directory: assets
130
+ run: cosign sign-blob --yes --bundle SHA256SUMS.sigstore.json SHA256SUMS
131
+ - name: GitHub Release
132
+ env:
133
+ GH_TOKEN: ${{ github.token }}
134
+ run: >
135
+ gh release create "$GITHUB_REF_NAME" assets/*
136
+ --repo "$GITHUB_REPOSITORY" --verify-tag --generate-notes --title "$GITHUB_REF_NAME"
137
+
138
+ pypi:
139
+ needs: release
140
+ runs-on: ubuntu-latest
141
+ environment: pypi
142
+ permissions:
143
+ id-token: write # trusted publishing
144
+ steps:
145
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
146
+ with:
147
+ name: release-python
148
+ path: dist
149
+ - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
150
+
151
+ image:
152
+ needs: python
153
+ runs-on: ubuntu-latest
154
+ permissions:
155
+ contents: read
156
+ packages: write
157
+ id-token: write
158
+ attestations: write
159
+ steps:
160
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
161
+ with:
162
+ persist-credentials: false
163
+ - name: Image name
164
+ id: meta
165
+ run: |
166
+ owner="$(echo "$GITHUB_REPOSITORY_OWNER" | tr '[:upper:]' '[:lower:]')"
167
+ echo "name=ghcr.io/$owner/threatwright" >> "$GITHUB_OUTPUT"
168
+ echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
169
+ - uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
170
+ - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
171
+ with:
172
+ registry: ghcr.io
173
+ username: ${{ github.actor }}
174
+ password: ${{ github.token }}
175
+ - uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
176
+ id: build
177
+ with:
178
+ context: .
179
+ push: true
180
+ tags: ${{ steps.meta.outputs.name }}:${{ steps.meta.outputs.version }}
181
+ provenance: mode=max
182
+ sbom: true
183
+ - uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
184
+ with:
185
+ subject-name: ${{ steps.meta.outputs.name }}
186
+ subject-digest: ${{ steps.build.outputs.digest }}
187
+ push-to-registry: true
@@ -0,0 +1,72 @@
1
+ # --- AI assistant / local tooling: never publish -------------------------
2
+ .claude/
3
+ CLAUDE.md
4
+ CLAUDE.local.md
5
+ **/CLAUDE.md
6
+ **/CLAUDE.local.md
7
+ .mcp.json
8
+ graphify-out/
9
+ .cursor/
10
+ .aider*
11
+ .continue/
12
+ .copilot/
13
+ AGENTS.md
14
+
15
+ # --- Private notes (customer references, drafts): never publish -------------
16
+ .private/
17
+
18
+ # --- Secrets and local config ---------------------------------------------
19
+ .env
20
+ .env.*
21
+ !.env.example
22
+ *.pem
23
+ *.key
24
+ *.p12
25
+ *.pfx
26
+ *.kdbx
27
+ secrets/
28
+ *.local.yaml
29
+ *.local.yml
30
+
31
+ # --- Python -----------------------------------------------------------------
32
+ __pycache__/
33
+ *.py[cod]
34
+ *.egg-info/
35
+ .venv/
36
+ venv/
37
+ .python-version
38
+ .mypy_cache/
39
+ .ruff_cache/
40
+ .pytest_cache/
41
+ .coverage
42
+ .coverage.*
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+
47
+ # --- Node / frontend ----------------------------------------------------------
48
+ node_modules/
49
+ .svelte-kit/
50
+ app/dist/
51
+ src/threatwright/web/
52
+
53
+ # --- Build artefacts ---------------------------------------------------------
54
+ build/
55
+ dist/
56
+ *.spec.bak
57
+ sbom*.json
58
+ playwright-report/
59
+ test-results/
60
+
61
+ # --- Editors / OS ------------------------------------------------------------
62
+ .idea/
63
+ .vscode/
64
+ *.swp
65
+ *~
66
+ .DS_Store
67
+ Thumbs.db
68
+ desktop.ini
69
+
70
+ # --- Office lock files -------------------------------------------------------
71
+ ~$*
72
+ .~lock.*#
@@ -0,0 +1,13 @@
1
+ repos:
2
+ - repo: https://github.com/gitleaks/gitleaks
3
+ rev: v8.30.1
4
+ hooks:
5
+ - id: gitleaks
6
+ - repo: local
7
+ hooks:
8
+ - id: forbidden-files
9
+ name: forbidden files
10
+ entry: python scripts/check_forbidden_files.py
11
+ language: system
12
+ pass_filenames: false
13
+ always_run: true
@@ -0,0 +1,9 @@
1
+ # Hooks offered to other repositories (docs/ci.md). Pass the project folder via `args`,
2
+ # e.g. `args: [--strict, threatmodel]`; default is the repository root.
3
+ - id: threatwright-validate
4
+ name: threatwright validate
5
+ description: Check a Threatwright project (schema, references, rules).
6
+ entry: threatwright validate
7
+ language: python
8
+ files: \.ya?ml$
9
+ pass_filenames: false
@@ -0,0 +1,37 @@
1
+ # CI runtime image (ADR-0009): threatwright CLI + LibreOffice Writer for PDF, no GUI.
2
+ # Base images pinned by digest (multi-arch index), looked up 2026-10-19; bump deliberately.
3
+
4
+ # --- 1: frontend bundle ------------------------------------------------------------
5
+ FROM node:24-slim@sha256:a5f4366e834695d5f363b920c104953a535d3a9864d1bdf74566a0ebe01daee5 AS frontend
6
+ WORKDIR /src/app
7
+ COPY app/package.json app/package-lock.json ./
8
+ RUN npm ci --no-audit --no-fund
9
+ COPY app/ ./
10
+ # vite writes to ../src/threatwright/web
11
+ RUN mkdir -p /src/src/threatwright && npm run build
12
+
13
+ # --- 2: wheel + locked requirements ----------------------------------------------
14
+ FROM python:3.13-slim@sha256:70729b46c69b4f1e97c4822c1af3df53a1476cf5ddc6c087c0c10bc3a5678c2f AS wheel
15
+ COPY --from=ghcr.io/astral-sh/uv:0.13.1@sha256:4a1f3666816dafadd20ceb71eac9a7d56d7ef30279f7d64048519ab901ada336 /uv /usr/local/bin/uv
16
+ WORKDIR /src
17
+ COPY pyproject.toml uv.lock README.md LICENSE ./
18
+ COPY src/ src/
19
+ COPY --from=frontend /src/src/threatwright/web src/threatwright/web
20
+ RUN uv build --wheel --out-dir /dist \
21
+ && uv export --frozen --no-dev --no-emit-project --format requirements-txt -o /dist/requirements.txt
22
+
23
+ # --- 3: runtime --------------------------------------------------------------------
24
+ FROM python:3.13-slim@sha256:70729b46c69b4f1e97c4822c1af3df53a1476cf5ddc6c087c0c10bc3a5678c2f
25
+ # git: diff against tags in CI. LibreOffice Writer (headless) for PDF output.
26
+ RUN apt-get update \
27
+ && apt-get install -y --no-install-recommends git libreoffice-writer-nogui fonts-dejavu-core \
28
+ && rm -rf /var/lib/apt/lists/*
29
+ COPY --from=wheel /dist /tmp/dist
30
+ RUN pip install --no-cache-dir --require-hashes -r /tmp/dist/requirements.txt \
31
+ && pip install --no-cache-dir --no-deps /tmp/dist/*.whl \
32
+ && rm -rf /tmp/dist
33
+ RUN useradd --create-home --uid 10001 threatwright
34
+ USER threatwright
35
+ WORKDIR /work
36
+ ENTRYPOINT ["threatwright"]
37
+ CMD ["--help"]