ladex 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 (109) hide show
  1. ladex-0.1.0/.gitattributes +7 -0
  2. ladex-0.1.0/.gitignore +45 -0
  3. ladex-0.1.0/.pre-commit-config.yaml +26 -0
  4. ladex-0.1.0/.python-version +1 -0
  5. ladex-0.1.0/LICENSE +21 -0
  6. ladex-0.1.0/PKG-INFO +164 -0
  7. ladex-0.1.0/README.md +138 -0
  8. ladex-0.1.0/assets/ladex-lockup-dark.png +0 -0
  9. ladex-0.1.0/assets/ladex-lockup-light.png +0 -0
  10. ladex-0.1.0/extensions/vscode/.gitignore +3 -0
  11. ladex-0.1.0/extensions/vscode/.vscode/launch.json +23 -0
  12. ladex-0.1.0/extensions/vscode/.vscode/tasks.json +12 -0
  13. ladex-0.1.0/extensions/vscode/.vscodeignore +8 -0
  14. ladex-0.1.0/extensions/vscode/LICENSE +21 -0
  15. ladex-0.1.0/extensions/vscode/README.md +53 -0
  16. ladex-0.1.0/extensions/vscode/demo/example.py +20 -0
  17. ladex-0.1.0/extensions/vscode/icon.png +0 -0
  18. ladex-0.1.0/extensions/vscode/ladex-0.1.0.vsix +0 -0
  19. ladex-0.1.0/extensions/vscode/out/extension.js +73 -0
  20. ladex-0.1.0/extensions/vscode/out/extension.js.map +1 -0
  21. ladex-0.1.0/extensions/vscode/package-lock.json +3972 -0
  22. ladex-0.1.0/extensions/vscode/package.json +73 -0
  23. ladex-0.1.0/extensions/vscode/src/extension.ts +56 -0
  24. ladex-0.1.0/extensions/vscode/tsconfig.json +15 -0
  25. ladex-0.1.0/packaging/entry.py +12 -0
  26. ladex-0.1.0/packaging/ladex.spec +64 -0
  27. ladex-0.1.0/pyproject.toml +98 -0
  28. ladex-0.1.0/src/ladex/__init__.py +8 -0
  29. ladex-0.1.0/src/ladex/cli/__init__.py +394 -0
  30. ladex-0.1.0/src/ladex/cli/report.py +306 -0
  31. ladex-0.1.0/src/ladex/engine/__init__.py +1 -0
  32. ladex-0.1.0/src/ladex/engine/attest/__init__.py +31 -0
  33. ladex-0.1.0/src/ladex/engine/attest/service.py +69 -0
  34. ladex-0.1.0/src/ladex/engine/attest/signer.py +107 -0
  35. ladex-0.1.0/src/ladex/engine/attest/statement.py +61 -0
  36. ladex-0.1.0/src/ladex/engine/attest/store.py +100 -0
  37. ladex-0.1.0/src/ladex/engine/bom/__init__.py +7 -0
  38. ladex-0.1.0/src/ladex/engine/bom/cyclonedx.py +215 -0
  39. ladex-0.1.0/src/ladex/engine/detect/__init__.py +8 -0
  40. ladex-0.1.0/src/ladex/engine/detect/ast_walker.py +263 -0
  41. ladex-0.1.0/src/ladex/engine/detect/iac.py +346 -0
  42. ladex-0.1.0/src/ladex/engine/detect/records.py +47 -0
  43. ladex-0.1.0/src/ladex/engine/enrich/__init__.py +34 -0
  44. ladex-0.1.0/src/ladex/engine/enrich/cache.py +98 -0
  45. ladex-0.1.0/src/ladex/engine/enrich/hfhub.py +74 -0
  46. ladex-0.1.0/src/ladex/engine/enrich/http.py +84 -0
  47. ladex-0.1.0/src/ladex/engine/enrich/models.py +104 -0
  48. ladex-0.1.0/src/ladex/engine/enrich/osv.py +53 -0
  49. ladex-0.1.0/src/ladex/engine/enrich/pypi.py +59 -0
  50. ladex-0.1.0/src/ladex/engine/enrich/service.py +73 -0
  51. ladex-0.1.0/src/ladex/engine/policy/__init__.py +41 -0
  52. ladex-0.1.0/src/ladex/engine/policy/context.py +71 -0
  53. ladex-0.1.0/src/ladex/engine/policy/evaluate.py +93 -0
  54. ladex-0.1.0/src/ladex/engine/policy/loader.py +91 -0
  55. ladex-0.1.0/src/ladex/engine/policy/models.py +108 -0
  56. ladex-0.1.0/src/ladex/engine/policy/report.py +62 -0
  57. ladex-0.1.0/src/ladex/engine/policy/service.py +16 -0
  58. ladex-0.1.0/src/ladex/engine/scan.py +116 -0
  59. ladex-0.1.0/src/ladex/engine/server/__init__.py +8 -0
  60. ladex-0.1.0/src/ladex/engine/server/diagnostics.py +55 -0
  61. ladex-0.1.0/src/ladex/engine/server/server.py +51 -0
  62. ladex-0.1.0/src/ladex/engine/taxonomy/__init__.py +41 -0
  63. ladex-0.1.0/src/ladex/engine/taxonomy/loader.py +128 -0
  64. ladex-0.1.0/src/ladex/engine/taxonomy/models.py +146 -0
  65. ladex-0.1.0/src/ladex/packs/__init__.py +1 -0
  66. ladex-0.1.0/src/ladex/packs/iac/iac.yaml +59 -0
  67. ladex-0.1.0/src/ladex/packs/policy/eu_ai_act/art50.yaml +42 -0
  68. ladex-0.1.0/src/ladex/packs/taxonomy/frameworks.yaml +46 -0
  69. ladex-0.1.0/src/ladex/packs/taxonomy/inference_apis.yaml +73 -0
  70. ladex-0.1.0/src/ladex/packs/taxonomy/model_loaders.yaml +66 -0
  71. ladex-0.1.0/src/ladex/packs/taxonomy/vector_stores.yaml +37 -0
  72. ladex-0.1.0/src/ladex/py.typed +0 -0
  73. ladex-0.1.0/tests/__init__.py +0 -0
  74. ladex-0.1.0/tests/attest/__init__.py +0 -0
  75. ladex-0.1.0/tests/attest/test_attest.py +104 -0
  76. ladex-0.1.0/tests/attest/test_attest_bom.py +55 -0
  77. ladex-0.1.0/tests/attest/test_attest_cli.py +87 -0
  78. ladex-0.1.0/tests/bom/__init__.py +0 -0
  79. ladex-0.1.0/tests/bom/test_bom_cli.py +31 -0
  80. ladex-0.1.0/tests/bom/test_cyclonedx.py +134 -0
  81. ladex-0.1.0/tests/detect/__init__.py +0 -0
  82. ladex-0.1.0/tests/detect/test_detector.py +116 -0
  83. ladex-0.1.0/tests/detect/test_fixture_repo.py +67 -0
  84. ladex-0.1.0/tests/detect/test_iac.py +127 -0
  85. ladex-0.1.0/tests/detect/test_scan.py +58 -0
  86. ladex-0.1.0/tests/detect/test_scan_cli.py +42 -0
  87. ladex-0.1.0/tests/enrich/__init__.py +0 -0
  88. ladex-0.1.0/tests/enrich/conftest.py +43 -0
  89. ladex-0.1.0/tests/enrich/test_cache.py +82 -0
  90. ladex-0.1.0/tests/enrich/test_providers.py +142 -0
  91. ladex-0.1.0/tests/enrich/test_service.py +76 -0
  92. ladex-0.1.0/tests/fixtures/iac/main.tf +41 -0
  93. ladex-0.1.0/tests/fixtures/iac/workloads.yaml +41 -0
  94. ladex-0.1.0/tests/fixtures/sample_repo/agents.py +12 -0
  95. ladex-0.1.0/tests/fixtures/sample_repo/broken.py +7 -0
  96. ladex-0.1.0/tests/fixtures/sample_repo/models.py +9 -0
  97. ladex-0.1.0/tests/fixtures/sample_repo/noise.py +12 -0
  98. ladex-0.1.0/tests/fixtures/sample_repo/store.py +7 -0
  99. ladex-0.1.0/tests/policy/__init__.py +0 -0
  100. ladex-0.1.0/tests/policy/test_bundles.py +86 -0
  101. ladex-0.1.0/tests/policy/test_evaluate.py +122 -0
  102. ladex-0.1.0/tests/policy/test_policy_cli.py +53 -0
  103. ladex-0.1.0/tests/server/__init__.py +0 -0
  104. ladex-0.1.0/tests/server/test_diagnostics.py +56 -0
  105. ladex-0.1.0/tests/taxonomy/__init__.py +0 -0
  106. ladex-0.1.0/tests/taxonomy/test_builtin_packs.py +73 -0
  107. ladex-0.1.0/tests/taxonomy/test_schema_validation.py +135 -0
  108. ladex-0.1.0/tests/test_smoke.py +25 -0
  109. ladex-0.1.0/uv.lock +1890 -0
@@ -0,0 +1,7 @@
1
+ # Normalize line endings to LF in the repo; check out native on Windows.
2
+ * text=auto eol=lf
3
+
4
+ # Binary / generated — never touch.
5
+ uv.lock text eol=lf
6
+ *.png binary
7
+ *.pdf binary
ladex-0.1.0/.gitignore ADDED
@@ -0,0 +1,45 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ *.so
9
+
10
+ # PyInstaller single-binary build outputs (artifacts go to GitHub Releases)
11
+ dist-bin/
12
+ build-bin/
13
+
14
+ # Virtualenv / uv
15
+ .venv/
16
+ venv/
17
+
18
+ # Tooling caches
19
+ .mypy_cache/
20
+ .ruff_cache/
21
+ .pytest_cache/
22
+ .cache/
23
+ htmlcov/
24
+ .coverage
25
+ .coverage.*
26
+
27
+ # IDE / OS
28
+ .idea/
29
+ .vscode/*
30
+ !.vscode/extensions.json
31
+ .DS_Store
32
+ Thumbs.db
33
+
34
+ # Node (VS Code extension, Step 8)
35
+ node_modules/
36
+
37
+ # Local secrets / env
38
+ .env
39
+ .env.*
40
+
41
+ # Personal learning notes (never committed)
42
+ notes/
43
+
44
+ # Project context / constitution — kept local, not committed
45
+ CLAUDE.md
@@ -0,0 +1,26 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.6.9
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ exclude: ^tests/fixtures/
8
+ - id: ruff-format
9
+ exclude: ^tests/fixtures/
10
+
11
+ - repo: https://github.com/pre-commit/mirrors-mypy
12
+ rev: v1.11.2
13
+ hooks:
14
+ - id: mypy
15
+ additional_dependencies:
16
+ [
17
+ pytest>=8.3,
18
+ pydantic>=2.7,
19
+ types-PyYAML>=6.0,
20
+ rich>=13.7,
21
+ cyclonedx-python-lib>=8.0,
22
+ pygls>=1.3,
23
+ ]
24
+ args: [--strict]
25
+ files: ^(src|tests)/
26
+ exclude: ^tests/fixtures/
@@ -0,0 +1 @@
1
+ 3.12
ladex-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 duskyvesper
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
ladex-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,164 @@
1
+ Metadata-Version: 2.5
2
+ Name: ladex
3
+ Version: 0.1.0
4
+ Summary: A bill of lading for AI — shift-left AI governance and ML-BOM generation for developers.
5
+ Project-URL: Homepage, https://ladex.dev
6
+ Project-URL: Repository, https://github.com/aibhuyan/ladex
7
+ Author-email: aibhuyan <bhuyanalimrans@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: ai-governance,aibom,cyclonedx,eu-ai-act,ml-bom,sbom
11
+ Requires-Python: >=3.12
12
+ Requires-Dist: cryptography>=42.0
13
+ Requires-Dist: cyclonedx-python-lib>=8.0
14
+ Requires-Dist: httpx>=0.27
15
+ Requires-Dist: platformdirs>=4.0
16
+ Requires-Dist: pydantic>=2.7
17
+ Requires-Dist: pygls>=1.3
18
+ Requires-Dist: python-hcl2>=4.3
19
+ Requires-Dist: pyyaml>=6.0
20
+ Requires-Dist: rich>=13.7
21
+ Requires-Dist: tree-sitter-python>=0.23
22
+ Requires-Dist: tree-sitter>=0.23
23
+ Provides-Extra: sigstore
24
+ Requires-Dist: sigstore>=3.0; extra == 'sigstore'
25
+ Description-Content-Type: text/markdown
26
+
27
+ <p align="center">
28
+ <picture>
29
+ <source media="(prefers-color-scheme: dark)" srcset="assets/ladex-lockup-dark.png">
30
+ <img src="assets/ladex-lockup-light.png" alt="Ladex" width="360">
31
+ </picture>
32
+ </p>
33
+
34
+ <p align="center"><strong>A bill of lading for AI.</strong></p>
35
+
36
+ <p align="center">
37
+ <img src="https://img.shields.io/badge/version-0.1.0-3b82f6?style=flat" alt="version 0.1.0">
38
+ <img src="https://img.shields.io/github/stars/aibhuyan/ladex?style=flat&color=3b82f6" alt="GitHub stars">
39
+ <img src="https://img.shields.io/badge/license-MIT-3b82f6?style=flat" alt="license MIT">
40
+ <img src="https://img.shields.io/badge/python-3.12+-3b82f6?style=flat" alt="python 3.12+">
41
+ <img src="https://img.shields.io/badge/tests-139%20passing-22c55e?style=flat" alt="tests 139 passing">
42
+ <img src="https://img.shields.io/badge/output-CycloneDX%20ML--BOM-3b82f6?style=flat" alt="CycloneDX ML-BOM">
43
+ <img src="https://img.shields.io/badge/EU%20AI%20Act-Art.%2050-3b82f6?style=flat" alt="EU AI Act Art. 50">
44
+ </p>
45
+
46
+ ---
47
+
48
+ You already require a **bill of lading** for physical cargo and an **SBOM** for software.
49
+ Ladex is the one for **AI** — it records what AI is aboard your codebase, from whom, and under
50
+ what terms, captured at the moment the code is written rather than discovered after the fact.
51
+
52
+ Ladex is a shift-left AI governance tool for developers. When you write an AI-relevant line of
53
+ code — importing an agent framework, loading a Hugging Face model, calling an inference API,
54
+ provisioning a GPU node pool in Terraform — Ladex detects it and answers three questions:
55
+
56
+ 1. **What is this?** &nbsp;model / dataset / agent framework / vector store / inference API
57
+ 2. **What does it obligate?** &nbsp;EU AI Act Art. 50 disclosure, Annex III high-risk triggers
58
+ 3. **What's auto-verifiable vs. what needs a human?** &nbsp;CVEs and licenses resolve
59
+ automatically. Training-data provenance and consent basis can't be derived by any scanner —
60
+ they're flagged `UNDOCUMENTED` and require a **signed human attestation**, never a fake green
61
+ checkmark.
62
+
63
+ The output is a **CycloneDX ML-BOM** committed to your repo, diffable in PRs, with signed
64
+ attestations for the fields no tool can derive.
65
+
66
+ > Ladex records what's aboard; it does not block attacks.
67
+
68
+ ## What it does
69
+
70
+ ```
71
+ detect (Python + Terraform + Kubernetes)
72
+ → enrich PyPI licenses · OSV CVEs · Hugging Face model cards (cached, offline-capable)
73
+ → obligate EU AI Act Art. 50 — applies / may-apply / silent; derivable vs. attestation
74
+ → BOM deterministic CycloneDX ML-BOM that diffs cleanly in PRs
75
+ → attest in-toto/DSSE signature fills an UNDOCUMENTED gap with a verifiable declaration
76
+
77
+ surfaces: CLI + VS Code (LSP, inline diagnostics as you type) — one shared engine
78
+ ```
79
+
80
+ ## Install
81
+
82
+ Requires [uv](https://docs.astral.sh/uv/) and Python 3.12.
83
+
84
+ ```bash
85
+ git clone https://github.com/aibhuyan/ladex
86
+ cd ladex
87
+ uv sync
88
+ uv run ladex --version
89
+ ```
90
+
91
+ ## Quickstart
92
+
93
+ ```bash
94
+ # See every AI component in a repo (silent on non-AI code)
95
+ uv run ladex scan path/to/repo
96
+
97
+ # Add real facts: licenses, CVEs, model cards (cached; --offline works from cache)
98
+ uv run ladex scan path/to/repo --enrich
99
+
100
+ # What does it obligate under the EU AI Act? (declare project facts to resolve "may apply")
101
+ uv run ladex policy check path/to/repo --user-facing
102
+
103
+ # Produce the committable, deterministic ML-BOM
104
+ uv run ladex scan path/to/repo --write-bom aibom.cdx.json
105
+
106
+ # Sign a human answer for a gap no scanner can fill, then verify it
107
+ uv run ladex attest "sentence-transformers/all-MiniLM-L6-v2" \
108
+ --claim provenance --value "Curated public corpora, reviewed 2026-08"
109
+ uv run ladex verify
110
+ ```
111
+
112
+ ### Example
113
+
114
+ ```
115
+ app.py
116
+ 7:10 inference_api openai.client openai.OpenAI (OpenAI)
117
+ 12:9 model openai.model-id gpt-4o (OpenAI)
118
+
119
+ infra/main.tf
120
+ 20:1 vector_store iac.tf.vector-store-unencrypted HIGH aws_opensearch_domain.vectors
121
+ - Vector store is not encrypted at rest
122
+
123
+ Summary: 3 detection(s) across 2 of 2 file(s) scanned.
124
+ ```
125
+
126
+ ## In your editor
127
+
128
+ The VS Code extension is a thin client over the same engine — inline diagnostics as you type,
129
+ nothing on non-AI code. Install it, no repo checkout needed:
130
+
131
+ 1. Install the engine so the extension can call it: `pip install ladex` (or `uv tool install ladex`).
132
+ 2. Grab `ladex-<version>.vsix` from the [Releases page](https://github.com/aibhuyan/ladex/releases)
133
+ → Extensions panel → **Install from VSIX…** (Marketplace listing coming soon).
134
+
135
+ Then open any Python file that uses an AI library. See
136
+ [`extensions/vscode/README.md`](extensions/vscode/README.md) for configuration and development.
137
+
138
+ ## Design principles
139
+
140
+ - **One engine, three surfaces.** The IDE, CLI, and (v2) PR check all call the same Python
141
+ engine — the editor can never disagree with the gate.
142
+ - **Ruthless silence.** If a line isn't AI-relevant, Ladex says nothing.
143
+ - **Honest gaps.** `UNDOCUMENTED` is a valid, valuable output. A green checkmark only appears
144
+ when something was actually verified — or signed by a named human.
145
+ - **Policy as versioned data.** Taxonomy and EU AI Act rules are updatable bundles, not code.
146
+
147
+ ## Scope (v1)
148
+
149
+ **Python + Terraform + Kubernetes detection. EU AI Act. Two surfaces (CLI + VS Code).**
150
+ The GitHub PR check and evidence graph are v2.
151
+
152
+ ## Development
153
+
154
+ ```bash
155
+ uv run ruff check .
156
+ uv run mypy
157
+ uv run pytest
158
+ ```
159
+
160
+ Pre-commit (`ruff` + `mypy`) runs on every commit; run `uv run pre-commit install` once.
161
+
162
+ ## License
163
+
164
+ MIT — see [`LICENSE`](LICENSE).
ladex-0.1.0/README.md ADDED
@@ -0,0 +1,138 @@
1
+ <p align="center">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="assets/ladex-lockup-dark.png">
4
+ <img src="assets/ladex-lockup-light.png" alt="Ladex" width="360">
5
+ </picture>
6
+ </p>
7
+
8
+ <p align="center"><strong>A bill of lading for AI.</strong></p>
9
+
10
+ <p align="center">
11
+ <img src="https://img.shields.io/badge/version-0.1.0-3b82f6?style=flat" alt="version 0.1.0">
12
+ <img src="https://img.shields.io/github/stars/aibhuyan/ladex?style=flat&color=3b82f6" alt="GitHub stars">
13
+ <img src="https://img.shields.io/badge/license-MIT-3b82f6?style=flat" alt="license MIT">
14
+ <img src="https://img.shields.io/badge/python-3.12+-3b82f6?style=flat" alt="python 3.12+">
15
+ <img src="https://img.shields.io/badge/tests-139%20passing-22c55e?style=flat" alt="tests 139 passing">
16
+ <img src="https://img.shields.io/badge/output-CycloneDX%20ML--BOM-3b82f6?style=flat" alt="CycloneDX ML-BOM">
17
+ <img src="https://img.shields.io/badge/EU%20AI%20Act-Art.%2050-3b82f6?style=flat" alt="EU AI Act Art. 50">
18
+ </p>
19
+
20
+ ---
21
+
22
+ You already require a **bill of lading** for physical cargo and an **SBOM** for software.
23
+ Ladex is the one for **AI** — it records what AI is aboard your codebase, from whom, and under
24
+ what terms, captured at the moment the code is written rather than discovered after the fact.
25
+
26
+ Ladex is a shift-left AI governance tool for developers. When you write an AI-relevant line of
27
+ code — importing an agent framework, loading a Hugging Face model, calling an inference API,
28
+ provisioning a GPU node pool in Terraform — Ladex detects it and answers three questions:
29
+
30
+ 1. **What is this?** &nbsp;model / dataset / agent framework / vector store / inference API
31
+ 2. **What does it obligate?** &nbsp;EU AI Act Art. 50 disclosure, Annex III high-risk triggers
32
+ 3. **What's auto-verifiable vs. what needs a human?** &nbsp;CVEs and licenses resolve
33
+ automatically. Training-data provenance and consent basis can't be derived by any scanner —
34
+ they're flagged `UNDOCUMENTED` and require a **signed human attestation**, never a fake green
35
+ checkmark.
36
+
37
+ The output is a **CycloneDX ML-BOM** committed to your repo, diffable in PRs, with signed
38
+ attestations for the fields no tool can derive.
39
+
40
+ > Ladex records what's aboard; it does not block attacks.
41
+
42
+ ## What it does
43
+
44
+ ```
45
+ detect (Python + Terraform + Kubernetes)
46
+ → enrich PyPI licenses · OSV CVEs · Hugging Face model cards (cached, offline-capable)
47
+ → obligate EU AI Act Art. 50 — applies / may-apply / silent; derivable vs. attestation
48
+ → BOM deterministic CycloneDX ML-BOM that diffs cleanly in PRs
49
+ → attest in-toto/DSSE signature fills an UNDOCUMENTED gap with a verifiable declaration
50
+
51
+ surfaces: CLI + VS Code (LSP, inline diagnostics as you type) — one shared engine
52
+ ```
53
+
54
+ ## Install
55
+
56
+ Requires [uv](https://docs.astral.sh/uv/) and Python 3.12.
57
+
58
+ ```bash
59
+ git clone https://github.com/aibhuyan/ladex
60
+ cd ladex
61
+ uv sync
62
+ uv run ladex --version
63
+ ```
64
+
65
+ ## Quickstart
66
+
67
+ ```bash
68
+ # See every AI component in a repo (silent on non-AI code)
69
+ uv run ladex scan path/to/repo
70
+
71
+ # Add real facts: licenses, CVEs, model cards (cached; --offline works from cache)
72
+ uv run ladex scan path/to/repo --enrich
73
+
74
+ # What does it obligate under the EU AI Act? (declare project facts to resolve "may apply")
75
+ uv run ladex policy check path/to/repo --user-facing
76
+
77
+ # Produce the committable, deterministic ML-BOM
78
+ uv run ladex scan path/to/repo --write-bom aibom.cdx.json
79
+
80
+ # Sign a human answer for a gap no scanner can fill, then verify it
81
+ uv run ladex attest "sentence-transformers/all-MiniLM-L6-v2" \
82
+ --claim provenance --value "Curated public corpora, reviewed 2026-08"
83
+ uv run ladex verify
84
+ ```
85
+
86
+ ### Example
87
+
88
+ ```
89
+ app.py
90
+ 7:10 inference_api openai.client openai.OpenAI (OpenAI)
91
+ 12:9 model openai.model-id gpt-4o (OpenAI)
92
+
93
+ infra/main.tf
94
+ 20:1 vector_store iac.tf.vector-store-unencrypted HIGH aws_opensearch_domain.vectors
95
+ - Vector store is not encrypted at rest
96
+
97
+ Summary: 3 detection(s) across 2 of 2 file(s) scanned.
98
+ ```
99
+
100
+ ## In your editor
101
+
102
+ The VS Code extension is a thin client over the same engine — inline diagnostics as you type,
103
+ nothing on non-AI code. Install it, no repo checkout needed:
104
+
105
+ 1. Install the engine so the extension can call it: `pip install ladex` (or `uv tool install ladex`).
106
+ 2. Grab `ladex-<version>.vsix` from the [Releases page](https://github.com/aibhuyan/ladex/releases)
107
+ → Extensions panel → **Install from VSIX…** (Marketplace listing coming soon).
108
+
109
+ Then open any Python file that uses an AI library. See
110
+ [`extensions/vscode/README.md`](extensions/vscode/README.md) for configuration and development.
111
+
112
+ ## Design principles
113
+
114
+ - **One engine, three surfaces.** The IDE, CLI, and (v2) PR check all call the same Python
115
+ engine — the editor can never disagree with the gate.
116
+ - **Ruthless silence.** If a line isn't AI-relevant, Ladex says nothing.
117
+ - **Honest gaps.** `UNDOCUMENTED` is a valid, valuable output. A green checkmark only appears
118
+ when something was actually verified — or signed by a named human.
119
+ - **Policy as versioned data.** Taxonomy and EU AI Act rules are updatable bundles, not code.
120
+
121
+ ## Scope (v1)
122
+
123
+ **Python + Terraform + Kubernetes detection. EU AI Act. Two surfaces (CLI + VS Code).**
124
+ The GitHub PR check and evidence graph are v2.
125
+
126
+ ## Development
127
+
128
+ ```bash
129
+ uv run ruff check .
130
+ uv run mypy
131
+ uv run pytest
132
+ ```
133
+
134
+ Pre-commit (`ruff` + `mypy`) runs on every commit; run `uv run pre-commit install` once.
135
+
136
+ ## License
137
+
138
+ MIT — see [`LICENSE`](LICENSE).
Binary file
@@ -0,0 +1,3 @@
1
+ node_modules/
2
+ out/
3
+ *.vsix
@@ -0,0 +1,23 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "Run Ladex Extension",
6
+ "type": "extensionHost",
7
+ "request": "launch",
8
+ // Load THIS extension and open the demo/ folder in the dev host window.
9
+ "args": [
10
+ "--extensionDevelopmentPath=${workspaceFolder}",
11
+ "${workspaceFolder}/demo"
12
+ ],
13
+ "outFiles": ["${workspaceFolder}/out/**/*.js"],
14
+ "preLaunchTask": "npm: compile",
15
+ // Put the project's virtualenv on PATH so the extension's default `ladex serve`
16
+ // resolves without a global install. Windows layout: <repo>/.venv/Scripts.
17
+ // (On macOS/Linux use ".venv/bin" and ":" as the separator.)
18
+ "env": {
19
+ "PATH": "${workspaceFolder}/../../.venv/Scripts;${env:PATH}"
20
+ }
21
+ }
22
+ ]
23
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "version": "2.0.0",
3
+ "tasks": [
4
+ {
5
+ "type": "npm",
6
+ "script": "compile",
7
+ "group": "build",
8
+ "problemMatcher": "$tsc",
9
+ "label": "npm: compile"
10
+ }
11
+ ]
12
+ }
@@ -0,0 +1,8 @@
1
+ src/**
2
+ node_modules/**
3
+ tsconfig.json
4
+ **/*.map
5
+ .gitignore
6
+ .vscode/**
7
+ demo/**
8
+ *.vsix
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 duskyvesper
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,53 @@
1
+ # Ladex for VS Code
2
+
3
+ Flags AI components inline as you edit Python — inference APIs, models, agent frameworks,
4
+ vector stores — and nudges what each obligates under the EU AI Act. Nothing shows on non-AI
5
+ code (ruthless silence).
6
+
7
+ All detection runs in the Ladex Python engine, the *same* engine the CLI and PR check use —
8
+ the editor can never disagree with the gate.
9
+
10
+ ## Install
11
+
12
+ **1. Install the Ladex engine** (the extension talks to it):
13
+
14
+ ```bash
15
+ pip install ladex # or: uv tool install ladex / pipx install ladex
16
+ ladex --version # verify it's on your PATH
17
+ ```
18
+
19
+ **2. Install the extension** — either:
20
+
21
+ - **From a `.vsix`:** download `ladex-<version>.vsix` from the
22
+ [Releases page](https://github.com/aibhuyan/ladex/releases), then in VS Code open the
23
+ Extensions panel → `⋯` menu → **Install from VSIX…** (or run
24
+ `code --install-extension ladex-<version>.vsix`).
25
+ - **From the Marketplace:** search **“Ladex”** in the Extensions panel *(once published)*.
26
+
27
+ Open any Python file that uses an AI library — diagnostics appear as you type.
28
+
29
+ ## Configuration
30
+
31
+ | Setting | Default | Meaning |
32
+ | --- | --- | --- |
33
+ | `ladex.serverCommand` | `ladex` | Command that starts the engine. Set to a full path if `ladex` isn't on PATH. |
34
+ | `ladex.serverArgs` | `["serve"]` | Arguments passed to it. |
35
+
36
+ If you see *“could not start 'ladex serve'”*, the engine isn't on your PATH — install it
37
+ (step 1) or point `ladex.serverCommand` at the executable
38
+ (e.g. `.../.venv/Scripts/ladex.exe`).
39
+
40
+ ## Development (contributing to the extension)
41
+
42
+ You only need this if you're hacking on the extension itself:
43
+
44
+ ```bash
45
+ cd extensions/vscode
46
+ npm install
47
+ npm run compile # or: npm run watch
48
+ ```
49
+
50
+ Then press **F5** — the bundled launch config compiles, puts the repo's `.venv` on PATH, and
51
+ opens `demo/` in an Extension Development Host so you can see live diagnostics.
52
+
53
+ Build a distributable package with `npm run package` → `ladex-<version>.vsix`.
@@ -0,0 +1,20 @@
1
+ """Ladex extension demo.
2
+
3
+ Open this file in the Extension Development Host (F5) and you should see inline Ladex
4
+ diagnostics on the AI-relevant lines below — and nothing on the ordinary Python.
5
+ Try editing: add `import transformers` and watch a new diagnostic appear as you type.
6
+ """
7
+
8
+ import openai
9
+ from anthropic import Anthropic
10
+
11
+ client = openai.OpenAI()
12
+ ac = Anthropic()
13
+
14
+ MODEL = "gpt-4o"
15
+ reply = ac.messages.create(model="claude-3-5-sonnet-latest", max_tokens=10, messages=[])
16
+
17
+
18
+ # Ordinary Python below — Ladex stays silent here (ruthless silence).
19
+ def add(a: int, b: int) -> int:
20
+ return a + b
Binary file
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ // Ladex VS Code extension — a thin client that launches the Python engine over stdio.
3
+ //
4
+ // It deliberately contains no detection logic: it starts `ladex serve` (the same engine the
5
+ // CLI and PR check use) and lets the language server publish diagnostics. "One engine, three
6
+ // surfaces" — the editor can never disagree with the gate.
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.activate = activate;
42
+ exports.deactivate = deactivate;
43
+ const vscode = __importStar(require("vscode"));
44
+ const node_1 = require("vscode-languageclient/node");
45
+ let client;
46
+ function activate(context) {
47
+ const config = vscode.workspace.getConfiguration("ladex");
48
+ const command = config.get("serverCommand", "ladex");
49
+ const args = config.get("serverArgs", ["serve"]);
50
+ const serverOptions = {
51
+ run: { command, args, transport: node_1.TransportKind.stdio },
52
+ debug: { command, args, transport: node_1.TransportKind.stdio },
53
+ };
54
+ const clientOptions = {
55
+ documentSelector: [{ scheme: "file", language: "python" }],
56
+ diagnosticCollectionName: "ladex",
57
+ };
58
+ client = new node_1.LanguageClient("ladex", "Ladex", serverOptions, clientOptions);
59
+ // Surface a clear error if the engine isn't on PATH, rather than failing silently.
60
+ client.start().catch((err) => {
61
+ void vscode.window.showErrorMessage(`Ladex: could not start '${command} ${args.join(" ")}'. ` +
62
+ `Install the ladex CLI and ensure it is on PATH. (${String(err)})`);
63
+ });
64
+ context.subscriptions.push({
65
+ dispose: () => {
66
+ void client?.stop();
67
+ },
68
+ });
69
+ }
70
+ function deactivate() {
71
+ return client?.stop();
72
+ }
73
+ //# sourceMappingURL=extension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":";AAAA,sFAAsF;AACtF,EAAE;AACF,4FAA4F;AAC5F,6FAA6F;AAC7F,2DAA2D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAY3D,4BAmCC;AAED,gCAEC;AAjDD,+CAAiC;AACjC,qDAKoC;AAEpC,IAAI,MAAkC,CAAC;AAEvC,SAAgB,QAAQ,CAAC,OAAgC;IACvD,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAS,eAAe,EAAE,OAAO,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAW,YAAY,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAE3D,MAAM,aAAa,GAAkB;QACnC,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,oBAAa,CAAC,KAAK,EAAE;QACtD,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,oBAAa,CAAC,KAAK,EAAE;KACzD,CAAC;IAEF,MAAM,aAAa,GAA0B;QAC3C,gBAAgB,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;QAC1D,wBAAwB,EAAE,OAAO;KAClC,CAAC;IAEF,MAAM,GAAG,IAAI,qBAAc,CACzB,OAAO,EACP,OAAO,EACP,aAAa,EACb,aAAa,CACd,CAAC;IAEF,mFAAmF;IACnF,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACpC,KAAK,MAAM,CAAC,MAAM,CAAC,gBAAgB,CACjC,2BAA2B,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK;YACvD,oDAAoD,MAAM,CAAC,GAAG,CAAC,GAAG,CACrE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC;QACzB,OAAO,EAAE,GAAG,EAAE;YACZ,KAAK,MAAM,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,UAAU;IACxB,OAAO,MAAM,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC"}