admina-framework 0.9.1__tar.gz → 0.9.3__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.
- {admina_framework-0.9.1/admina_framework.egg-info → admina_framework-0.9.3}/PKG-INFO +27 -26
- {admina_framework-0.9.1 → admina_framework-0.9.3}/README.md +24 -23
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/__init__.py +1 -1
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/cli/main.py +132 -17
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/dashboard/static/index.html +37 -30
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/data_sovereignty/pii.py +23 -6
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/registry.py +14 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/proxy/api/dashboard.py +7 -5
- {admina_framework-0.9.1 → admina_framework-0.9.3/admina_framework.egg-info}/PKG-INFO +27 -26
- {admina_framework-0.9.1 → admina_framework-0.9.3}/pyproject.toml +4 -3
- {admina_framework-0.9.1 → admina_framework-0.9.3}/tests/test_domains.py +17 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/LICENSE +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/NOTICE +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/cli/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/cli/commands/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/cli/templates/admina.yaml.j2 +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/cli/templates/docker-compose.yml.j2 +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/cli/templates/env.j2 +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/cli/templates/main.py.j2 +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/cli/templates/plugin.py.j2 +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/cli/templates/plugin_pyproject.toml.j2 +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/cli/templates/plugin_readme.md.j2 +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/cli/templates/plugin_test.py.j2 +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/core/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/core/config.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/core/event_bus.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/core/secrets.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/core/types.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/dashboard/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/dashboard/static/heimdall.png +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/dashboard/static/vendor/alpinejs.min.js +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/agent_security/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/agent_security/firewall.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/agent_security/loop_breaker.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/ai_infra/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/ai_infra/llm_engine.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/ai_infra/rag.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/ai_infra/webui.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/compliance/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/compliance/cross_regulation.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/compliance/eu_ai_act.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/compliance/forensic.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/compliance/gdpr.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/compliance/nis2.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/compliance/oisg.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/compliance/otel.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/data_sovereignty/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/data_sovereignty/classification.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/data_sovereignty/residency.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/integrations/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/integrations/_engines.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/integrations/cheshirecat/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/integrations/cheshirecat/admina-plugin/admina_governance.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/integrations/crewai/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/integrations/crewai/callbacks.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/integrations/langchain/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/integrations/langchain/callbacks.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/integrations/n8n/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/integrations/openclaw/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/base.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/adapters/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/adapters/ollama.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/adapters/openai.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/alerts/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/alerts/log.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/alerts/webhook.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/auth/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/auth/apikey.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/compliance/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/compliance/eu_ai_act.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/connectors/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/connectors/chromadb.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/connectors/filesystem.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/forensic/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/forensic/filesystem.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/forensic/minio.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/guards/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/guards/guardrailsai_guard.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/pii/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/pii/spacy_regex.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/transports/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/transports/http_rest.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/transports/mcp.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/proxy/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/proxy/api/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/proxy/api/integration.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/proxy/config.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/proxy/engine_bridge.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/proxy/governance.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/proxy/main.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/proxy/multi_upstream.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/proxy/state.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/py.typed +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/sdk/__init__.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/sdk/_compat.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/sdk/compliance_kit.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/sdk/governed_agent.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/sdk/governed_data.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina/sdk/governed_model.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina_framework.egg-info/SOURCES.txt +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina_framework.egg-info/dependency_links.txt +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina_framework.egg-info/entry_points.txt +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina_framework.egg-info/requires.txt +2 -2
- {admina_framework-0.9.1 → admina_framework-0.9.3}/admina_framework.egg-info/top_level.txt +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/setup.cfg +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/tests/test_benchmark_14us.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/tests/test_core_config.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/tests/test_governance_pipeline.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/tests/test_mcp_transport.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/tests/test_proxy_security.py +0 -0
- {admina_framework-0.9.1 → admina_framework-0.9.3}/tests/test_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: admina-framework
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.3
|
|
4
4
|
Summary: Admina — governed AI development framework
|
|
5
5
|
Author-email: Stefano Noferi <info@admina.org>
|
|
6
6
|
Maintainer-email: Stefano Noferi <info@admina.org>
|
|
@@ -43,10 +43,10 @@ Requires-Dist: boto3<2,>=1.34; extra == "proxy"
|
|
|
43
43
|
Requires-Dist: minio<8,>=7.2; extra == "proxy"
|
|
44
44
|
Requires-Dist: clickhouse-connect<1,>=0.7; extra == "proxy"
|
|
45
45
|
Requires-Dist: typer<1,>=0.9; extra == "proxy"
|
|
46
|
+
Requires-Dist: numpy<2,>=1.24; extra == "proxy"
|
|
47
|
+
Requires-Dist: scikit-learn<2,>=1.3; extra == "proxy"
|
|
46
48
|
Provides-Extra: nlp
|
|
47
49
|
Requires-Dist: spacy<4,>=3.8; extra == "nlp"
|
|
48
|
-
Requires-Dist: scikit-learn<2,>=1.3; extra == "nlp"
|
|
49
|
-
Requires-Dist: numpy<2,>=1.24; extra == "nlp"
|
|
50
50
|
Provides-Extra: telemetry
|
|
51
51
|
Requires-Dist: opentelemetry-api<2,>=1.20; extra == "telemetry"
|
|
52
52
|
Requires-Dist: opentelemetry-sdk<2,>=1.20; extra == "telemetry"
|
|
@@ -120,20 +120,22 @@ report = kit.gap_analysis(risk_category="high", current_compliance={...})
|
|
|
120
120
|
### Install from PyPI
|
|
121
121
|
|
|
122
122
|
```bash
|
|
123
|
-
# SDK
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
# Proxy + infrastructure deps
|
|
123
|
+
# Recommended for new users: SDK + proxy + dashboard.
|
|
124
|
+
# Lets you run `admina dev` and see the dashboard out of the box.
|
|
127
125
|
pip install "admina-framework[proxy]"
|
|
128
126
|
|
|
129
|
-
# Everything (proxy + NLP + telemetry)
|
|
127
|
+
# Everything (proxy + NLP + telemetry). Use this if you also want
|
|
128
|
+
# spaCy-based NER for PII detection or OpenTelemetry export.
|
|
130
129
|
pip install "admina-framework[full]"
|
|
130
|
+
python -m spacy download en_core_web_sm # for [full] only
|
|
131
131
|
|
|
132
|
-
#
|
|
133
|
-
python -m spacy download en_core_web_sm
|
|
134
|
-
|
|
135
|
-
# Optional: Rust-accelerated engine (auto-detected at runtime)
|
|
132
|
+
# Optional: Rust-accelerated engine (auto-detected at runtime).
|
|
136
133
|
pip install admina-core
|
|
134
|
+
|
|
135
|
+
# Advanced: SDK only (no proxy, no dashboard, no `admina dev`).
|
|
136
|
+
# Use this when embedding the SDK into another service and you don't
|
|
137
|
+
# need the local dev server.
|
|
138
|
+
pip install admina-framework
|
|
137
139
|
```
|
|
138
140
|
|
|
139
141
|
> The PyPI distribution name is `admina-framework`; the Python import
|
|
@@ -151,28 +153,27 @@ pip install admina-core
|
|
|
151
153
|
git clone https://github.com/admina-org/admina.git
|
|
152
154
|
cd admina
|
|
153
155
|
|
|
154
|
-
#
|
|
155
|
-
pip install -e .
|
|
156
|
-
python -c "from admina import GovernedModel; print('SDK ready')"
|
|
157
|
-
|
|
158
|
-
# Note: To use the OllamaAdapter, install Ollama (https://ollama.ai)
|
|
159
|
-
# and pull a model first: ollama pull llama3.1:8b
|
|
160
|
-
|
|
161
|
-
# Option 2: Proxy + infra deps
|
|
156
|
+
# Recommended: proxy + dashboard + infra deps (enables `admina dev`)
|
|
162
157
|
pip install -e ".[proxy]"
|
|
163
158
|
|
|
164
|
-
#
|
|
159
|
+
# Everything (proxy + NLP + telemetry)
|
|
165
160
|
pip install -e ".[full]"
|
|
166
161
|
|
|
167
|
-
#
|
|
162
|
+
# CLI workflow
|
|
163
|
+
admina init my-project # Scaffold a governed AI project
|
|
164
|
+
cd my-project # admina dev runs from the project directory
|
|
165
|
+
admina dev # Start the local proxy + dashboard
|
|
166
|
+
|
|
167
|
+
# Full stack via Docker (no [proxy] extra required)
|
|
168
168
|
./scripts/bootstrap-secrets.sh # Auto-generate .env with random credentials
|
|
169
169
|
docker compose up --build # Credentials printed at bootstrap
|
|
170
170
|
|
|
171
|
-
#
|
|
171
|
+
# Note: To use the OllamaAdapter, install Ollama (https://ollama.ai)
|
|
172
|
+
# and pull a model first: ollama pull llama3.1:8b
|
|
173
|
+
|
|
174
|
+
# Advanced: SDK only (no proxy, no dashboard)
|
|
172
175
|
pip install -e .
|
|
173
|
-
|
|
174
|
-
cd my-project # admina dev runs from the project directory
|
|
175
|
-
admina dev # Start local dev stack
|
|
176
|
+
python -c "from admina import GovernedModel; print('SDK ready')"
|
|
176
177
|
```
|
|
177
178
|
|
|
178
179
|
Dashboard: [http://localhost:3000](http://localhost:3000) | API docs: [http://localhost:8080/docs](http://localhost:8080/docs)
|
|
@@ -62,20 +62,22 @@ report = kit.gap_analysis(risk_category="high", current_compliance={...})
|
|
|
62
62
|
### Install from PyPI
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
|
-
# SDK
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
# Proxy + infrastructure deps
|
|
65
|
+
# Recommended for new users: SDK + proxy + dashboard.
|
|
66
|
+
# Lets you run `admina dev` and see the dashboard out of the box.
|
|
69
67
|
pip install "admina-framework[proxy]"
|
|
70
68
|
|
|
71
|
-
# Everything (proxy + NLP + telemetry)
|
|
69
|
+
# Everything (proxy + NLP + telemetry). Use this if you also want
|
|
70
|
+
# spaCy-based NER for PII detection or OpenTelemetry export.
|
|
72
71
|
pip install "admina-framework[full]"
|
|
72
|
+
python -m spacy download en_core_web_sm # for [full] only
|
|
73
73
|
|
|
74
|
-
#
|
|
75
|
-
python -m spacy download en_core_web_sm
|
|
76
|
-
|
|
77
|
-
# Optional: Rust-accelerated engine (auto-detected at runtime)
|
|
74
|
+
# Optional: Rust-accelerated engine (auto-detected at runtime).
|
|
78
75
|
pip install admina-core
|
|
76
|
+
|
|
77
|
+
# Advanced: SDK only (no proxy, no dashboard, no `admina dev`).
|
|
78
|
+
# Use this when embedding the SDK into another service and you don't
|
|
79
|
+
# need the local dev server.
|
|
80
|
+
pip install admina-framework
|
|
79
81
|
```
|
|
80
82
|
|
|
81
83
|
> The PyPI distribution name is `admina-framework`; the Python import
|
|
@@ -93,28 +95,27 @@ pip install admina-core
|
|
|
93
95
|
git clone https://github.com/admina-org/admina.git
|
|
94
96
|
cd admina
|
|
95
97
|
|
|
96
|
-
#
|
|
97
|
-
pip install -e .
|
|
98
|
-
python -c "from admina import GovernedModel; print('SDK ready')"
|
|
99
|
-
|
|
100
|
-
# Note: To use the OllamaAdapter, install Ollama (https://ollama.ai)
|
|
101
|
-
# and pull a model first: ollama pull llama3.1:8b
|
|
102
|
-
|
|
103
|
-
# Option 2: Proxy + infra deps
|
|
98
|
+
# Recommended: proxy + dashboard + infra deps (enables `admina dev`)
|
|
104
99
|
pip install -e ".[proxy]"
|
|
105
100
|
|
|
106
|
-
#
|
|
101
|
+
# Everything (proxy + NLP + telemetry)
|
|
107
102
|
pip install -e ".[full]"
|
|
108
103
|
|
|
109
|
-
#
|
|
104
|
+
# CLI workflow
|
|
105
|
+
admina init my-project # Scaffold a governed AI project
|
|
106
|
+
cd my-project # admina dev runs from the project directory
|
|
107
|
+
admina dev # Start the local proxy + dashboard
|
|
108
|
+
|
|
109
|
+
# Full stack via Docker (no [proxy] extra required)
|
|
110
110
|
./scripts/bootstrap-secrets.sh # Auto-generate .env with random credentials
|
|
111
111
|
docker compose up --build # Credentials printed at bootstrap
|
|
112
112
|
|
|
113
|
-
#
|
|
113
|
+
# Note: To use the OllamaAdapter, install Ollama (https://ollama.ai)
|
|
114
|
+
# and pull a model first: ollama pull llama3.1:8b
|
|
115
|
+
|
|
116
|
+
# Advanced: SDK only (no proxy, no dashboard)
|
|
114
117
|
pip install -e .
|
|
115
|
-
|
|
116
|
-
cd my-project # admina dev runs from the project directory
|
|
117
|
-
admina dev # Start local dev stack
|
|
118
|
+
python -c "from admina import GovernedModel; print('SDK ready')"
|
|
118
119
|
```
|
|
119
120
|
|
|
120
121
|
Dashboard: [http://localhost:3000](http://localhost:3000) | API docs: [http://localhost:8080/docs](http://localhost:8080/docs)
|
|
@@ -262,20 +262,61 @@ def init(
|
|
|
262
262
|
else:
|
|
263
263
|
click.echo(" ⚠ docker compose pull failed (you can run it later)")
|
|
264
264
|
|
|
265
|
-
# 5. Print next steps
|
|
266
|
-
click.echo(
|
|
267
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
268
|
-
Project ready!
|
|
265
|
+
# 5. Print next steps — tailored to what the user actually has installed.
|
|
266
|
+
click.echo(_format_next_steps(project_name))
|
|
269
267
|
|
|
270
|
-
Next steps:
|
|
271
|
-
cd {project_name}
|
|
272
|
-
admina dev # local mode (no Docker): proxy + dashboard on :3000
|
|
273
|
-
admina dev --stack # full Docker stack (proxy, redis, clickhouse, minio, grafana)
|
|
274
|
-
python main.py # run example (works without admina dev)
|
|
275
268
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
269
|
+
def _format_next_steps(project_name: str) -> str:
|
|
270
|
+
"""Build the post-init "Next steps" message based on detected extras.
|
|
271
|
+
|
|
272
|
+
Honest output: only suggest commands that will work with the user's
|
|
273
|
+
current install. Missing prerequisites are surfaced explicitly with
|
|
274
|
+
the exact upgrade command.
|
|
275
|
+
"""
|
|
276
|
+
proxy_ok = _proxy_extra_installed()
|
|
277
|
+
docker_ok = shutil.which("docker") is not None
|
|
278
|
+
|
|
279
|
+
lines: list[str] = [
|
|
280
|
+
"",
|
|
281
|
+
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━",
|
|
282
|
+
" Project ready!",
|
|
283
|
+
"",
|
|
284
|
+
" Next steps:",
|
|
285
|
+
f" cd {project_name}",
|
|
286
|
+
" python main.py # SDK example — works with any install",
|
|
287
|
+
]
|
|
288
|
+
if proxy_ok:
|
|
289
|
+
lines.append(" admina dev # local proxy + dashboard on :3000")
|
|
290
|
+
else:
|
|
291
|
+
lines.extend(
|
|
292
|
+
[
|
|
293
|
+
"",
|
|
294
|
+
" To run the local proxy + dashboard (admina dev), install the [proxy] extra:",
|
|
295
|
+
" pip install 'admina-framework[proxy]' --upgrade",
|
|
296
|
+
]
|
|
297
|
+
)
|
|
298
|
+
if docker_ok:
|
|
299
|
+
lines.append(
|
|
300
|
+
" admina dev --stack # full Docker stack "
|
|
301
|
+
"(proxy + redis + clickhouse + minio + grafana)"
|
|
302
|
+
)
|
|
303
|
+
else:
|
|
304
|
+
lines.extend(
|
|
305
|
+
[
|
|
306
|
+
"",
|
|
307
|
+
" To run the full Docker stack (admina dev --stack), install Docker:",
|
|
308
|
+
" https://docs.docker.com/get-docker/",
|
|
309
|
+
]
|
|
310
|
+
)
|
|
311
|
+
lines.extend(
|
|
312
|
+
[
|
|
313
|
+
"",
|
|
314
|
+
" Docs: https://admina.org/docs",
|
|
315
|
+
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━",
|
|
316
|
+
"",
|
|
317
|
+
]
|
|
318
|
+
)
|
|
319
|
+
return "\n".join(lines)
|
|
279
320
|
|
|
280
321
|
|
|
281
322
|
# ── admina dev helpers ─────────────────────────────────────
|
|
@@ -482,6 +523,46 @@ def _list_local_ipv4() -> list[str]:
|
|
|
482
523
|
return sorted(ips, key=lambda ip: (ip != "127.0.0.1", ip))
|
|
483
524
|
|
|
484
525
|
|
|
526
|
+
def _proxy_extra_installed() -> bool:
|
|
527
|
+
"""True if uvicorn + fastapi (the [proxy] extra) are importable."""
|
|
528
|
+
try:
|
|
529
|
+
import fastapi # noqa: F401
|
|
530
|
+
import uvicorn # noqa: F401
|
|
531
|
+
except ImportError:
|
|
532
|
+
return False
|
|
533
|
+
return True
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
def _require_proxy_extra_for_local_dev() -> None:
|
|
537
|
+
"""Exit cleanly with an actionable message when [proxy] is missing.
|
|
538
|
+
|
|
539
|
+
Local-mode `admina dev` shells out to uvicorn, which lives only in the
|
|
540
|
+
[proxy] extra. Without an early check, the user sees a cryptic
|
|
541
|
+
`No module named uvicorn` from python -m uvicorn.
|
|
542
|
+
"""
|
|
543
|
+
if _proxy_extra_installed():
|
|
544
|
+
return
|
|
545
|
+
click.echo("", err=True)
|
|
546
|
+
click.echo(" admina dev (local mode) requires the [proxy] extra.", err=True)
|
|
547
|
+
click.echo(" Install one of:", err=True)
|
|
548
|
+
click.echo(
|
|
549
|
+
" pip install 'admina-framework[proxy]' --upgrade",
|
|
550
|
+
err=True,
|
|
551
|
+
)
|
|
552
|
+
click.echo(
|
|
553
|
+
" pip install 'admina-framework[full]' --upgrade # adds NLP + telemetry",
|
|
554
|
+
err=True,
|
|
555
|
+
)
|
|
556
|
+
click.echo("", err=True)
|
|
557
|
+
click.echo(
|
|
558
|
+
" Or run the full Docker stack (no [proxy] extra required):",
|
|
559
|
+
err=True,
|
|
560
|
+
)
|
|
561
|
+
click.echo(" admina dev --stack", err=True)
|
|
562
|
+
click.echo("", err=True)
|
|
563
|
+
raise SystemExit(1)
|
|
564
|
+
|
|
565
|
+
|
|
485
566
|
def _run_local(
|
|
486
567
|
project_dir: Path,
|
|
487
568
|
vault: SecretVault,
|
|
@@ -491,6 +572,8 @@ def _run_local(
|
|
|
491
572
|
host: str,
|
|
492
573
|
) -> None:
|
|
493
574
|
"""Run proxy + dashboard as a single uvicorn process (no Docker)."""
|
|
575
|
+
_require_proxy_extra_for_local_dev()
|
|
576
|
+
|
|
494
577
|
# Auto-detect free port: if preferred is taken (Docker Desktop, Grafana,
|
|
495
578
|
# another node dev server on :3000…), fall back to the next free port.
|
|
496
579
|
try:
|
|
@@ -1032,6 +1115,8 @@ def doctor() -> None:
|
|
|
1032
1115
|
issues.append(f"Missing: pip install {pkg_name}")
|
|
1033
1116
|
|
|
1034
1117
|
# ── Optional extras ──────────────────────────────────────
|
|
1118
|
+
# Each group lists (import_name, pypi_name) tuples. numpy + scikit-learn
|
|
1119
|
+
# are part of [proxy] (LoopBreaker requires them), not [nlp].
|
|
1035
1120
|
click.echo("\n Optional extras:")
|
|
1036
1121
|
extras = {
|
|
1037
1122
|
"proxy": [
|
|
@@ -1042,16 +1127,17 @@ def doctor() -> None:
|
|
|
1042
1127
|
("redis", "redis"),
|
|
1043
1128
|
("minio", "minio"),
|
|
1044
1129
|
("clickhouse_connect", "clickhouse-connect"),
|
|
1130
|
+
("numpy", "numpy"),
|
|
1131
|
+
("sklearn", "scikit-learn"),
|
|
1045
1132
|
],
|
|
1046
1133
|
"nlp": [
|
|
1047
1134
|
("spacy", "spacy"),
|
|
1048
|
-
("sklearn", "scikit-learn"),
|
|
1049
|
-
("numpy", "numpy"),
|
|
1050
1135
|
],
|
|
1051
1136
|
"telemetry": [
|
|
1052
1137
|
("opentelemetry", "opentelemetry-api"),
|
|
1053
1138
|
],
|
|
1054
1139
|
}
|
|
1140
|
+
extras_status: dict[str, str] = {}
|
|
1055
1141
|
for group, mods in extras.items():
|
|
1056
1142
|
present = 0
|
|
1057
1143
|
for mod_name, _ in mods:
|
|
@@ -1062,12 +1148,25 @@ def doctor() -> None:
|
|
|
1062
1148
|
pass
|
|
1063
1149
|
if present == len(mods):
|
|
1064
1150
|
click.echo(f" [{group}]{' ' * (16 - len(group))} {ok_mark} ({present}/{len(mods)})")
|
|
1151
|
+
extras_status[group] = "ok"
|
|
1065
1152
|
elif present > 0:
|
|
1066
1153
|
click.echo(
|
|
1067
1154
|
f" [{group}]{' ' * (16 - len(group))} {warn_mark} ({present}/{len(mods)})"
|
|
1068
1155
|
)
|
|
1156
|
+
extras_status[group] = "partial"
|
|
1069
1157
|
else:
|
|
1070
1158
|
click.echo(f" [{group}]{' ' * (16 - len(group))} -- not installed")
|
|
1159
|
+
extras_status[group] = "missing"
|
|
1160
|
+
|
|
1161
|
+
if extras_status.get("proxy") != "ok":
|
|
1162
|
+
click.echo(
|
|
1163
|
+
f" {warn_mark} admina dev (local mode) needs the [proxy] extra — "
|
|
1164
|
+
"pip install 'admina-framework[proxy]' --upgrade"
|
|
1165
|
+
)
|
|
1166
|
+
issues.append(
|
|
1167
|
+
"admina dev (local mode) requires the [proxy] extra — "
|
|
1168
|
+
"run: pip install 'admina-framework[proxy]' --upgrade"
|
|
1169
|
+
)
|
|
1071
1170
|
|
|
1072
1171
|
# ── spaCy NER model ──────────────────────────────────────
|
|
1073
1172
|
click.echo("\n NLP engine:")
|
|
@@ -1078,12 +1177,28 @@ def doctor() -> None:
|
|
|
1078
1177
|
spacy.load("en_core_web_sm")
|
|
1079
1178
|
click.echo(f" en_core_web_sm {ok_mark}")
|
|
1080
1179
|
except OSError:
|
|
1180
|
+
# PII still works in regex-only mode without the spaCy model, so
|
|
1181
|
+
# this is a soft warning rather than a blocking issue.
|
|
1081
1182
|
click.echo(
|
|
1082
|
-
f" en_core_web_sm {warn_mark}
|
|
1183
|
+
f" en_core_web_sm {warn_mark} not loadable "
|
|
1184
|
+
"(PII falls back to regex-only — install for NER coverage)"
|
|
1185
|
+
)
|
|
1186
|
+
# The model is not on PyPI — it ships as a direct wheel URL
|
|
1187
|
+
# from explosion/spacy-models on GitHub. `python -m spacy
|
|
1188
|
+
# download` is the canonical command but needs pip in the
|
|
1189
|
+
# venv; for uv venvs (which omit pip) point at the wheel URL.
|
|
1190
|
+
model_ver = "3.8.0" # matches spacy>=3.8,<4 pinned in [nlp]
|
|
1191
|
+
wheel_url = (
|
|
1192
|
+
"https://github.com/explosion/spacy-models/releases/download/"
|
|
1193
|
+
f"en_core_web_sm-{model_ver}/en_core_web_sm-{model_ver}-py3-none-any.whl"
|
|
1083
1194
|
)
|
|
1084
|
-
|
|
1195
|
+
click.echo(f" Install with: {sys.executable} -m spacy download en_core_web_sm")
|
|
1196
|
+
click.echo(f" For uv venvs: uv pip install {wheel_url}")
|
|
1085
1197
|
except ImportError:
|
|
1086
|
-
click.echo(
|
|
1198
|
+
click.echo(
|
|
1199
|
+
" spacy -- not installed "
|
|
1200
|
+
"(PII falls back to regex-only — install [nlp] extra for NER)"
|
|
1201
|
+
)
|
|
1087
1202
|
|
|
1088
1203
|
# ── Rust engine ──────────────────────────────────────────
|
|
1089
1204
|
click.echo("\n Governance engine:")
|
|
@@ -932,36 +932,43 @@ function dashboard() {
|
|
|
932
932
|
|
|
933
933
|
// ── Fetch all data ─────────────────────────────────
|
|
934
934
|
async refresh() {
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
935
|
+
// allSettled so one failing endpoint never blanks the whole dashboard.
|
|
936
|
+
const okJson = async (url) => {
|
|
937
|
+
const r = await fetch(url);
|
|
938
|
+
if (!r.ok) throw new Error(`${url} -> ${r.status}`);
|
|
939
|
+
return r.json();
|
|
940
|
+
};
|
|
941
|
+
const results = await Promise.allSettled([
|
|
942
|
+
okJson('/api/dashboard/score'),
|
|
943
|
+
okJson('/api/dashboard/compliance'),
|
|
944
|
+
okJson('/api/dashboard/sovereignty'),
|
|
945
|
+
okJson('/api/stats'),
|
|
946
|
+
okJson('/api/dashboard/feed?limit=50'),
|
|
947
|
+
okJson('/api/dashboard/infra'),
|
|
948
|
+
okJson('/api/dashboard/models'),
|
|
949
|
+
okJson('/api/dashboard/oisg'),
|
|
950
|
+
]);
|
|
951
|
+
const [scoreRes, compRes, sovRes, statsRes, feedRes, infraRes, modelsRes, oisgRes] =
|
|
952
|
+
results.map(r => r.status === 'fulfilled' ? r.value : null);
|
|
953
|
+
|
|
954
|
+
if (scoreRes) this.score = scoreRes;
|
|
955
|
+
if (compRes) this.complianceData = compRes;
|
|
956
|
+
if (sovRes) this.sovereignty = sovRes;
|
|
957
|
+
if (statsRes) this.stats = statsRes;
|
|
958
|
+
if (infraRes) this.infraData = infraRes;
|
|
959
|
+
if (modelsRes) this.modelData = modelsRes;
|
|
960
|
+
if (oisgRes) this.oisg = oisgRes;
|
|
961
|
+
|
|
962
|
+
const failed = results.filter(r => r.status === 'rejected');
|
|
963
|
+
if (failed.length) {
|
|
964
|
+
failed.forEach(r => console.warn('[Admina] endpoint failed:', r.reason));
|
|
965
|
+
}
|
|
966
|
+
this.healthy = failed.length === 0;
|
|
967
|
+
this.lastUpdate = new Date().toLocaleTimeString();
|
|
968
|
+
|
|
969
|
+
// Seed the feed with historical events if WS hasn't provided any yet
|
|
970
|
+
if (this.feedEvents.length === 0 && feedRes?.events?.length > 0) {
|
|
971
|
+
this.feedEvents = feedRes.events.slice(0, 50).map(e => this._formatFeedEvent(e));
|
|
965
972
|
}
|
|
966
973
|
},
|
|
967
974
|
|
|
@@ -21,7 +21,12 @@ import logging
|
|
|
21
21
|
import os
|
|
22
22
|
import re
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
# spaCy is part of the [nlp] extra. When absent, PIIRedactor falls back
|
|
25
|
+
# to regex-only mode (still covers EMAIL/PHONE/SSN/IBAN/IP/credit-card/EU IDs).
|
|
26
|
+
try:
|
|
27
|
+
import spacy as _spacy
|
|
28
|
+
except ImportError:
|
|
29
|
+
_spacy = None # type: ignore[assignment]
|
|
25
30
|
|
|
26
31
|
logger = logging.getLogger("admina.pii_redactor")
|
|
27
32
|
|
|
@@ -152,12 +157,24 @@ class PIIRedactor:
|
|
|
152
157
|
def __init__(self, config=None):
|
|
153
158
|
# Resolve NLP model: config.ner_model > ADMINA_SPACY_MODEL env var > default
|
|
154
159
|
model_name = getattr(config, "ner_model", None) or SPACY_MODEL
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
+
if _spacy is None:
|
|
161
|
+
logger.info(
|
|
162
|
+
"spaCy not installed — PII redaction running in regex-only mode "
|
|
163
|
+
"(install admina-framework[nlp] for NER-based detection)"
|
|
164
|
+
)
|
|
160
165
|
self.nlp = None
|
|
166
|
+
else:
|
|
167
|
+
try:
|
|
168
|
+
self.nlp = _spacy.load(model_name)
|
|
169
|
+
logger.info("[OK] spaCy model loaded: %s", model_name)
|
|
170
|
+
except OSError:
|
|
171
|
+
logger.warning(
|
|
172
|
+
"spaCy model '%s' not found — using regex-only mode "
|
|
173
|
+
"(run: python -m spacy download %s)",
|
|
174
|
+
model_name,
|
|
175
|
+
model_name,
|
|
176
|
+
)
|
|
177
|
+
self.nlp = None
|
|
161
178
|
|
|
162
179
|
# Build active categories: start from PII_CATEGORIES defaults, then
|
|
163
180
|
# disable any category not listed in config.categories (if provided).
|
|
@@ -284,6 +284,13 @@ class PluginRegistry:
|
|
|
284
284
|
mod = importlib.util.module_from_spec(spec)
|
|
285
285
|
sys.modules[mod_name] = mod
|
|
286
286
|
spec.loader.exec_module(mod)
|
|
287
|
+
except ModuleNotFoundError as exc:
|
|
288
|
+
logger.warning(
|
|
289
|
+
"Skipping plugin %s — optional dependency %r not installed",
|
|
290
|
+
py_file.stem,
|
|
291
|
+
exc.name or "?",
|
|
292
|
+
)
|
|
293
|
+
return 0
|
|
287
294
|
except (ImportError, AttributeError, RuntimeError):
|
|
288
295
|
logger.warning("Failed to import plugin file %s", py_file, exc_info=True)
|
|
289
296
|
return 0
|
|
@@ -294,6 +301,13 @@ class PluginRegistry:
|
|
|
294
301
|
"""Import a module by dotted path and register all plugin classes."""
|
|
295
302
|
try:
|
|
296
303
|
mod = importlib.import_module(mod_path)
|
|
304
|
+
except ModuleNotFoundError as exc:
|
|
305
|
+
logger.warning(
|
|
306
|
+
"Skipping plugin module %r — optional dependency %r not installed",
|
|
307
|
+
mod_path,
|
|
308
|
+
exc.name or "?",
|
|
309
|
+
)
|
|
310
|
+
return 0
|
|
297
311
|
except ImportError:
|
|
298
312
|
logger.warning("Failed to import plugin module %r", mod_path, exc_info=True)
|
|
299
313
|
return 0
|
|
@@ -450,9 +450,13 @@ def create_dashboard_endpoints(
|
|
|
450
450
|
|
|
451
451
|
# Upstream MCP
|
|
452
452
|
http = get_http_client() if get_http_client else None
|
|
453
|
-
if
|
|
454
|
-
|
|
453
|
+
upstream = get_settings().UPSTREAM_MCP_URL if get_settings else ""
|
|
454
|
+
if http is None or not upstream.startswith(("http://", "https://")):
|
|
455
|
+
services["upstream_mcp"] = {"status": "not_configured"}
|
|
456
|
+
else:
|
|
455
457
|
try:
|
|
458
|
+
import httpx
|
|
459
|
+
|
|
456
460
|
t0 = time.perf_counter()
|
|
457
461
|
resp = await http.get(f"{upstream}/health", timeout=3.0)
|
|
458
462
|
latency = round((time.perf_counter() - t0) * 1000, 2)
|
|
@@ -461,13 +465,11 @@ def create_dashboard_endpoints(
|
|
|
461
465
|
"latency_ms": latency,
|
|
462
466
|
"url": upstream,
|
|
463
467
|
}
|
|
464
|
-
except (OSError, RuntimeError):
|
|
468
|
+
except (OSError, RuntimeError, httpx.HTTPError):
|
|
465
469
|
services["upstream_mcp"] = {
|
|
466
470
|
"status": "unreachable",
|
|
467
471
|
"url": upstream,
|
|
468
472
|
}
|
|
469
|
-
else:
|
|
470
|
-
services["upstream_mcp"] = {"status": "not_configured"}
|
|
471
473
|
|
|
472
474
|
healthy_count = sum(1 for s in services.values() if s.get("status") == "healthy")
|
|
473
475
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: admina-framework
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.3
|
|
4
4
|
Summary: Admina — governed AI development framework
|
|
5
5
|
Author-email: Stefano Noferi <info@admina.org>
|
|
6
6
|
Maintainer-email: Stefano Noferi <info@admina.org>
|
|
@@ -43,10 +43,10 @@ Requires-Dist: boto3<2,>=1.34; extra == "proxy"
|
|
|
43
43
|
Requires-Dist: minio<8,>=7.2; extra == "proxy"
|
|
44
44
|
Requires-Dist: clickhouse-connect<1,>=0.7; extra == "proxy"
|
|
45
45
|
Requires-Dist: typer<1,>=0.9; extra == "proxy"
|
|
46
|
+
Requires-Dist: numpy<2,>=1.24; extra == "proxy"
|
|
47
|
+
Requires-Dist: scikit-learn<2,>=1.3; extra == "proxy"
|
|
46
48
|
Provides-Extra: nlp
|
|
47
49
|
Requires-Dist: spacy<4,>=3.8; extra == "nlp"
|
|
48
|
-
Requires-Dist: scikit-learn<2,>=1.3; extra == "nlp"
|
|
49
|
-
Requires-Dist: numpy<2,>=1.24; extra == "nlp"
|
|
50
50
|
Provides-Extra: telemetry
|
|
51
51
|
Requires-Dist: opentelemetry-api<2,>=1.20; extra == "telemetry"
|
|
52
52
|
Requires-Dist: opentelemetry-sdk<2,>=1.20; extra == "telemetry"
|
|
@@ -120,20 +120,22 @@ report = kit.gap_analysis(risk_category="high", current_compliance={...})
|
|
|
120
120
|
### Install from PyPI
|
|
121
121
|
|
|
122
122
|
```bash
|
|
123
|
-
# SDK
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
# Proxy + infrastructure deps
|
|
123
|
+
# Recommended for new users: SDK + proxy + dashboard.
|
|
124
|
+
# Lets you run `admina dev` and see the dashboard out of the box.
|
|
127
125
|
pip install "admina-framework[proxy]"
|
|
128
126
|
|
|
129
|
-
# Everything (proxy + NLP + telemetry)
|
|
127
|
+
# Everything (proxy + NLP + telemetry). Use this if you also want
|
|
128
|
+
# spaCy-based NER for PII detection or OpenTelemetry export.
|
|
130
129
|
pip install "admina-framework[full]"
|
|
130
|
+
python -m spacy download en_core_web_sm # for [full] only
|
|
131
131
|
|
|
132
|
-
#
|
|
133
|
-
python -m spacy download en_core_web_sm
|
|
134
|
-
|
|
135
|
-
# Optional: Rust-accelerated engine (auto-detected at runtime)
|
|
132
|
+
# Optional: Rust-accelerated engine (auto-detected at runtime).
|
|
136
133
|
pip install admina-core
|
|
134
|
+
|
|
135
|
+
# Advanced: SDK only (no proxy, no dashboard, no `admina dev`).
|
|
136
|
+
# Use this when embedding the SDK into another service and you don't
|
|
137
|
+
# need the local dev server.
|
|
138
|
+
pip install admina-framework
|
|
137
139
|
```
|
|
138
140
|
|
|
139
141
|
> The PyPI distribution name is `admina-framework`; the Python import
|
|
@@ -151,28 +153,27 @@ pip install admina-core
|
|
|
151
153
|
git clone https://github.com/admina-org/admina.git
|
|
152
154
|
cd admina
|
|
153
155
|
|
|
154
|
-
#
|
|
155
|
-
pip install -e .
|
|
156
|
-
python -c "from admina import GovernedModel; print('SDK ready')"
|
|
157
|
-
|
|
158
|
-
# Note: To use the OllamaAdapter, install Ollama (https://ollama.ai)
|
|
159
|
-
# and pull a model first: ollama pull llama3.1:8b
|
|
160
|
-
|
|
161
|
-
# Option 2: Proxy + infra deps
|
|
156
|
+
# Recommended: proxy + dashboard + infra deps (enables `admina dev`)
|
|
162
157
|
pip install -e ".[proxy]"
|
|
163
158
|
|
|
164
|
-
#
|
|
159
|
+
# Everything (proxy + NLP + telemetry)
|
|
165
160
|
pip install -e ".[full]"
|
|
166
161
|
|
|
167
|
-
#
|
|
162
|
+
# CLI workflow
|
|
163
|
+
admina init my-project # Scaffold a governed AI project
|
|
164
|
+
cd my-project # admina dev runs from the project directory
|
|
165
|
+
admina dev # Start the local proxy + dashboard
|
|
166
|
+
|
|
167
|
+
# Full stack via Docker (no [proxy] extra required)
|
|
168
168
|
./scripts/bootstrap-secrets.sh # Auto-generate .env with random credentials
|
|
169
169
|
docker compose up --build # Credentials printed at bootstrap
|
|
170
170
|
|
|
171
|
-
#
|
|
171
|
+
# Note: To use the OllamaAdapter, install Ollama (https://ollama.ai)
|
|
172
|
+
# and pull a model first: ollama pull llama3.1:8b
|
|
173
|
+
|
|
174
|
+
# Advanced: SDK only (no proxy, no dashboard)
|
|
172
175
|
pip install -e .
|
|
173
|
-
|
|
174
|
-
cd my-project # admina dev runs from the project directory
|
|
175
|
-
admina dev # Start local dev stack
|
|
176
|
+
python -c "from admina import GovernedModel; print('SDK ready')"
|
|
176
177
|
```
|
|
177
178
|
|
|
178
179
|
Dashboard: [http://localhost:3000](http://localhost:3000) | API docs: [http://localhost:8080/docs](http://localhost:8080/docs)
|
|
@@ -19,7 +19,7 @@ build-backend = "setuptools.build_meta"
|
|
|
19
19
|
|
|
20
20
|
[project]
|
|
21
21
|
name = "admina-framework"
|
|
22
|
-
version = "0.9.
|
|
22
|
+
version = "0.9.3"
|
|
23
23
|
description = "Admina — governed AI development framework"
|
|
24
24
|
readme = "README.md"
|
|
25
25
|
requires-python = ">=3.11"
|
|
@@ -80,6 +80,9 @@ proxy = [
|
|
|
80
80
|
"minio>=7.2,<8",
|
|
81
81
|
"clickhouse-connect>=0.7,<1",
|
|
82
82
|
"typer>=0.9,<1",
|
|
83
|
+
# Required by the LoopBreaker (core proxy guardrail — not an NLP add-on).
|
|
84
|
+
"numpy>=1.24,<2",
|
|
85
|
+
"scikit-learn>=1.3,<2",
|
|
83
86
|
]
|
|
84
87
|
nlp = [
|
|
85
88
|
# spacy 3.7.x ships an old blis (0.7.11) that fails to build on Python 3.13
|
|
@@ -92,8 +95,6 @@ nlp = [
|
|
|
92
95
|
# `admina-framework[nlp]`, run:
|
|
93
96
|
# python -m spacy download en_core_web_sm
|
|
94
97
|
# The PIIRedactor logs a clear error if the model is missing.
|
|
95
|
-
"scikit-learn>=1.3,<2",
|
|
96
|
-
"numpy>=1.24,<2",
|
|
97
98
|
]
|
|
98
99
|
telemetry = [
|
|
99
100
|
"opentelemetry-api>=1.20,<2",
|
|
@@ -295,6 +295,23 @@ class TestEngineBridge:
|
|
|
295
295
|
assert hasattr(pii, "redact")
|
|
296
296
|
assert hasattr(pii, "get_stats")
|
|
297
297
|
|
|
298
|
+
def test_pii_factory_without_spacy_installed(self, monkeypatch):
|
|
299
|
+
"""Regression: admina dev must boot even when spaCy is not installed.
|
|
300
|
+
|
|
301
|
+
Simulates a user who ran `pip install admina-framework[proxy]` without
|
|
302
|
+
the [nlp] extra. The PII bridge must fall back to regex-only mode
|
|
303
|
+
instead of crashing the proxy lifespan with ModuleNotFoundError.
|
|
304
|
+
"""
|
|
305
|
+
from admina.domains.data_sovereignty import pii as pii_mod
|
|
306
|
+
|
|
307
|
+
monkeypatch.setattr(pii_mod, "_spacy", None)
|
|
308
|
+
|
|
309
|
+
redactor = pii_mod.PIIRedactor()
|
|
310
|
+
assert redactor.nlp is None
|
|
311
|
+
r = redactor.redact("Contact john@example.com")
|
|
312
|
+
assert "john@example.com" not in r["redacted_text"]
|
|
313
|
+
assert r["count"] >= 1
|
|
314
|
+
|
|
298
315
|
def test_loop_breaker_factory(self):
|
|
299
316
|
from admina.proxy.engine_bridge import get_loop_breaker
|
|
300
317
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/cli/templates/docker-compose.yml.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/cli/templates/plugin_pyproject.toml.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/dashboard/static/vendor/alpinejs.min.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/agent_security/loop_breaker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/compliance/cross_regulation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/data_sovereignty/__init__.py
RENAMED
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/data_sovereignty/classification.py
RENAMED
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/domains/data_sovereignty/residency.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/integrations/cheshirecat/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/integrations/langchain/callbacks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/adapters/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/compliance/__init__.py
RENAMED
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/compliance/eu_ai_act.py
RENAMED
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/connectors/__init__.py
RENAMED
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/connectors/chromadb.py
RENAMED
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/connectors/filesystem.py
RENAMED
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/forensic/__init__.py
RENAMED
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/forensic/filesystem.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/transports/__init__.py
RENAMED
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina/plugins/builtin/transports/http_rest.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina_framework.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{admina_framework-0.9.1 → admina_framework-0.9.3}/admina_framework.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
@@ -8,8 +8,6 @@ admina-framework[nlp,proxy,telemetry]
|
|
|
8
8
|
|
|
9
9
|
[nlp]
|
|
10
10
|
spacy<4,>=3.8
|
|
11
|
-
scikit-learn<2,>=1.3
|
|
12
|
-
numpy<2,>=1.24
|
|
13
11
|
|
|
14
12
|
[proxy]
|
|
15
13
|
fastapi<1,>=0.104
|
|
@@ -23,6 +21,8 @@ boto3<2,>=1.34
|
|
|
23
21
|
minio<8,>=7.2
|
|
24
22
|
clickhouse-connect<1,>=0.7
|
|
25
23
|
typer<1,>=0.9
|
|
24
|
+
numpy<2,>=1.24
|
|
25
|
+
scikit-learn<2,>=1.3
|
|
26
26
|
|
|
27
27
|
[telemetry]
|
|
28
28
|
opentelemetry-api<2,>=1.20
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|