admina-framework 0.11.0__tar.gz → 0.11.1__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 (157) hide show
  1. {admina_framework-0.11.0/admina_framework.egg-info → admina_framework-0.11.1}/PKG-INFO +11 -4
  2. {admina_framework-0.11.0 → admina_framework-0.11.1}/README.md +9 -2
  3. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/__init__.py +1 -1
  4. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/proxy/api/dashboard.py +7 -2
  5. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/proxy/api/integration.py +20 -1
  6. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/proxy/config.py +3 -1
  7. {admina_framework-0.11.0 → admina_framework-0.11.1/admina_framework.egg-info}/PKG-INFO +11 -4
  8. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina_framework.egg-info/SOURCES.txt +2 -0
  9. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina_framework.egg-info/requires.txt +1 -1
  10. {admina_framework-0.11.0 → admina_framework-0.11.1}/pyproject.toml +3 -3
  11. admina_framework-0.11.1/tests/test_error_disclosure.py +72 -0
  12. admina_framework-0.11.1/tests/test_proxy_governance_mode_config.py +56 -0
  13. {admina_framework-0.11.0 → admina_framework-0.11.1}/LICENSE +0 -0
  14. {admina_framework-0.11.0 → admina_framework-0.11.1}/NOTICE +0 -0
  15. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/cli/__init__.py +0 -0
  16. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/cli/commands/__init__.py +0 -0
  17. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/cli/main.py +0 -0
  18. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/cli/templates/admina.yaml.j2 +0 -0
  19. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/cli/templates/docker-compose.yml.j2 +0 -0
  20. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/cli/templates/env.j2 +0 -0
  21. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/cli/templates/main.py.j2 +0 -0
  22. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/cli/templates/plugin.py.j2 +0 -0
  23. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/cli/templates/plugin_pyproject.toml.j2 +0 -0
  24. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/cli/templates/plugin_readme.md.j2 +0 -0
  25. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/cli/templates/plugin_test.py.j2 +0 -0
  26. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/core/__init__.py +0 -0
  27. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/core/config.py +0 -0
  28. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/core/event_bus.py +0 -0
  29. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/core/secrets.py +0 -0
  30. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/core/types.py +0 -0
  31. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/dashboard/__init__.py +0 -0
  32. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/dashboard/static/heimdall.png +0 -0
  33. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/dashboard/static/index.html +0 -0
  34. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/dashboard/static/vendor/alpinejs.min.js +0 -0
  35. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/__init__.py +0 -0
  36. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/agent_security/__init__.py +0 -0
  37. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/agent_security/firewall.py +0 -0
  38. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/agent_security/loop_breaker.py +0 -0
  39. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/ai_infra/__init__.py +0 -0
  40. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/ai_infra/llm_engine.py +0 -0
  41. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/ai_infra/rag.py +0 -0
  42. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/ai_infra/webui.py +0 -0
  43. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/compliance/__init__.py +0 -0
  44. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/compliance/cross_regulation.py +0 -0
  45. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/compliance/eu_ai_act.py +0 -0
  46. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/compliance/forensic.py +0 -0
  47. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/compliance/gdpr.py +0 -0
  48. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/compliance/nis2.py +0 -0
  49. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/compliance/oisg.py +0 -0
  50. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/compliance/otel.py +0 -0
  51. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/data_sovereignty/__init__.py +0 -0
  52. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/data_sovereignty/classification.py +0 -0
  53. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/data_sovereignty/pii.py +0 -0
  54. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/data_sovereignty/residency.py +0 -0
  55. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/domains/governance.py +0 -0
  56. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/engines/__init__.py +0 -0
  57. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/engines/presidio.py +0 -0
  58. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/integrations/__init__.py +0 -0
  59. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/integrations/_engines.py +0 -0
  60. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/integrations/cheshirecat/__init__.py +0 -0
  61. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/integrations/cheshirecat/admina-plugin/admina_governance.py +0 -0
  62. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/integrations/crewai/__init__.py +0 -0
  63. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/integrations/crewai/callbacks.py +0 -0
  64. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/integrations/langchain/__init__.py +0 -0
  65. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/integrations/langchain/callbacks.py +0 -0
  66. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/integrations/n8n/__init__.py +0 -0
  67. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/integrations/openclaw/__init__.py +0 -0
  68. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/__init__.py +0 -0
  69. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/base.py +0 -0
  70. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/__init__.py +0 -0
  71. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/adapters/__init__.py +0 -0
  72. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/adapters/_streaming.py +0 -0
  73. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/adapters/anthropic.py +0 -0
  74. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/adapters/bedrock.py +0 -0
  75. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/adapters/gemini.py +0 -0
  76. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/adapters/mistral.py +0 -0
  77. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/adapters/ollama.py +0 -0
  78. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/adapters/openai.py +0 -0
  79. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/adapters/vllm.py +0 -0
  80. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/alerts/__init__.py +0 -0
  81. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/alerts/log.py +0 -0
  82. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/alerts/webhook.py +0 -0
  83. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/auth/__init__.py +0 -0
  84. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/auth/apikey.py +0 -0
  85. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/compliance/__init__.py +0 -0
  86. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/compliance/eu_ai_act.py +0 -0
  87. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/connectors/__init__.py +0 -0
  88. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/connectors/chromadb.py +0 -0
  89. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/connectors/filesystem.py +0 -0
  90. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/forensic/__init__.py +0 -0
  91. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/forensic/filesystem.py +0 -0
  92. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/guards/__init__.py +0 -0
  93. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/guards/guardrailsai_guard.py +0 -0
  94. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/pii/__init__.py +0 -0
  95. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/pii/spacy_regex.py +0 -0
  96. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/transports/__init__.py +0 -0
  97. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/transports/http_rest.py +0 -0
  98. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/builtin/transports/mcp.py +0 -0
  99. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/plugins/registry.py +0 -0
  100. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/proxy/__init__.py +0 -0
  101. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/proxy/api/__init__.py +0 -0
  102. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/proxy/api/gateway.py +0 -0
  103. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/proxy/engine_bridge.py +0 -0
  104. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/proxy/governance.py +0 -0
  105. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/proxy/main.py +0 -0
  106. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/proxy/multi_upstream.py +0 -0
  107. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/proxy/state.py +0 -0
  108. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/py.typed +0 -0
  109. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/redteam/__init__.py +0 -0
  110. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/redteam/baselines/baseline.json +0 -0
  111. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/redteam/corpora/SHA256SUMS +0 -0
  112. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/redteam/corpora/injection.jsonl +0 -0
  113. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/redteam/corpora/loop.jsonl +0 -0
  114. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/redteam/corpora/pii.jsonl +0 -0
  115. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/redteam/corpora.py +0 -0
  116. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/redteam/detectors.py +0 -0
  117. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/redteam/gate.py +0 -0
  118. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/redteam/metrics.py +0 -0
  119. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/redteam/report.py +0 -0
  120. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/redteam/runner.py +0 -0
  121. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/sdk/__init__.py +0 -0
  122. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/sdk/_compat.py +0 -0
  123. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/sdk/compliance_kit.py +0 -0
  124. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/sdk/errors.py +0 -0
  125. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/sdk/governed_agent.py +0 -0
  126. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/sdk/governed_data.py +0 -0
  127. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/sdk/governed_model.py +0 -0
  128. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/sdk/retry.py +0 -0
  129. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina/sdk/streaming.py +0 -0
  130. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina_framework.egg-info/dependency_links.txt +0 -0
  131. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina_framework.egg-info/entry_points.txt +0 -0
  132. {admina_framework-0.11.0 → admina_framework-0.11.1}/admina_framework.egg-info/top_level.txt +0 -0
  133. {admina_framework-0.11.0 → admina_framework-0.11.1}/setup.cfg +0 -0
  134. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_benchmark_14us.py +0 -0
  135. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_core_config.py +0 -0
  136. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_domains.py +0 -0
  137. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_domains_governance.py +0 -0
  138. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_engines.py +0 -0
  139. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_firewall_parity.py +0 -0
  140. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_forensic_blackbox.py +0 -0
  141. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_gateway_config.py +0 -0
  142. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_gateway_endpoints.py +0 -0
  143. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_gateway_guard_fail_mode.py +0 -0
  144. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_gateway_helpers.py +0 -0
  145. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_gateway_mount.py +0 -0
  146. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_governance_pipeline.py +0 -0
  147. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_guard_fail_mode.py +0 -0
  148. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_mcp_transport.py +0 -0
  149. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_presidio_engine.py +0 -0
  150. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_proxy_forensic_would_action.py +0 -0
  151. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_proxy_guard_fail_mode.py +0 -0
  152. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_proxy_mcp_response_pii.py +0 -0
  153. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_proxy_plugins.py +0 -0
  154. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_proxy_security.py +0 -0
  155. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_redteam_efficacy.py +0 -0
  156. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_redteam_lib.py +0 -0
  157. {admina_framework-0.11.0 → admina_framework-0.11.1}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: admina-framework
3
- Version: 0.11.0
3
+ Version: 0.11.1
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>
@@ -30,7 +30,7 @@ License-File: NOTICE
30
30
  Requires-Dist: pyyaml<7,>=6.0
31
31
  Requires-Dist: click<9,>=8.1
32
32
  Requires-Dist: jinja2<4,>=3.1
33
- Requires-Dist: cryptography<50,>=41.0
33
+ Requires-Dist: cryptography<51,>=41.0
34
34
  Provides-Extra: proxy
35
35
  Requires-Dist: fastapi<1,>=0.104; extra == "proxy"
36
36
  Requires-Dist: uvicorn[standard]<1,>=0.24; extra == "proxy"
@@ -331,16 +331,23 @@ from admina import GovernedModel, GovernedData, GovernedAgent, ComplianceKit
331
331
 
332
332
  | Interface | Builtin implementations |
333
333
  |-----------|------------------------|
334
- | Model Adapter | Ollama, OpenAI |
334
+ | Model Adapter | Ollama, OpenAI, Anthropic, Gemini, Mistral, Bedrock, vLLM |
335
335
  | Data Connector | ChromaDB, Filesystem |
336
336
  | Governance Domain | GuardrailsAI (toxic, jailbreak, bias, PII) |
337
337
  | Compliance Template | EU AI Act |
338
338
  | Transport Adapter | MCP, HTTP REST |
339
339
  | Forensic Store | Filesystem, S3-compatible (boto3 — AWS S3, MinIO, R2, …) |
340
340
  | Auth Provider | API Key |
341
- | PII Engine | spaCy + Regex |
341
+ | PII Engine | spaCy + Regex (default), Microsoft Presidio (`pip install admina-framework[presidio]`, `ADMINA_PII_ENGINE=presidio`) |
342
342
  | Alert Channel | Log, Webhook |
343
343
 
344
+ Model adapters lazy-import their provider SDK, so install the ones you
345
+ use: `pip install admina-framework[adapters]` for all of them, or a
346
+ single provider (`[openai]`, `[ollama]`, `[anthropic]`, `[mistral]`,
347
+ `[gemini]`, `[bedrock]`). vLLM has no extra of its own — it serves an
348
+ OpenAI-compatible API and subclasses the OpenAI adapter, so install
349
+ `[openai]` for it.
350
+
344
351
  ```bash
345
352
  admina plugin list # List registered plugins
346
353
  admina plugin install ./my-plugin # Install a custom plugin
@@ -254,16 +254,23 @@ from admina import GovernedModel, GovernedData, GovernedAgent, ComplianceKit
254
254
 
255
255
  | Interface | Builtin implementations |
256
256
  |-----------|------------------------|
257
- | Model Adapter | Ollama, OpenAI |
257
+ | Model Adapter | Ollama, OpenAI, Anthropic, Gemini, Mistral, Bedrock, vLLM |
258
258
  | Data Connector | ChromaDB, Filesystem |
259
259
  | Governance Domain | GuardrailsAI (toxic, jailbreak, bias, PII) |
260
260
  | Compliance Template | EU AI Act |
261
261
  | Transport Adapter | MCP, HTTP REST |
262
262
  | Forensic Store | Filesystem, S3-compatible (boto3 — AWS S3, MinIO, R2, …) |
263
263
  | Auth Provider | API Key |
264
- | PII Engine | spaCy + Regex |
264
+ | PII Engine | spaCy + Regex (default), Microsoft Presidio (`pip install admina-framework[presidio]`, `ADMINA_PII_ENGINE=presidio`) |
265
265
  | Alert Channel | Log, Webhook |
266
266
 
267
+ Model adapters lazy-import their provider SDK, so install the ones you
268
+ use: `pip install admina-framework[adapters]` for all of them, or a
269
+ single provider (`[openai]`, `[ollama]`, `[anthropic]`, `[mistral]`,
270
+ `[gemini]`, `[bedrock]`). vLLM has no extra of its own — it serves an
271
+ OpenAI-compatible API and subclasses the OpenAI adapter, so install
272
+ `[openai]` for it.
273
+
267
274
  ```bash
268
275
  admina plugin list # List registered plugins
269
276
  admina plugin install ./my-plugin # Install a custom plugin
@@ -23,7 +23,7 @@ from __future__ import annotations
23
23
 
24
24
  from admina.sdk import ComplianceKit, GovernedAgent, GovernedData, GovernedModel
25
25
 
26
- __version__ = "0.11.0"
26
+ __version__ = "0.11.1"
27
27
 
28
28
  __all__ = [
29
29
  "__version__",
@@ -407,7 +407,11 @@ def create_dashboard_endpoints(
407
407
  "used_memory_bytes": info.get("used_memory", 0),
408
408
  }
409
409
  except (OSError, RuntimeError) as exc:
410
- services["redis"] = {"status": "unhealthy", "error": str(exc)}
410
+ # The exception text can carry connection details (host, port,
411
+ # credentials embedded in a URL); log it server-side and return
412
+ # a generic reason, as the other dashboard queries already do.
413
+ logger.warning("Redis health check failed: %s", exc)
414
+ services["redis"] = {"status": "unhealthy", "error": "Health check failed"}
411
415
  else:
412
416
  services["redis"] = {"status": "not_configured"}
413
417
 
@@ -432,9 +436,10 @@ def create_dashboard_endpoints(
432
436
  "event_count": row_count,
433
437
  }
434
438
  except (OSError, RuntimeError, Exception) as exc:
439
+ logger.warning("ClickHouse health check failed: %s", exc)
435
440
  services["clickhouse"] = {
436
441
  "status": "unhealthy",
437
- "error": str(exc),
442
+ "error": "Health check failed",
438
443
  }
439
444
  else:
440
445
  services["clickhouse"] = {"status": "not_configured"}
@@ -37,6 +37,25 @@ class _DefaultSettings:
37
37
  GOVERNANCE_MODE: str = "enforce"
38
38
 
39
39
 
40
+ def _scrub_check_errors(checks: dict[str, Any]) -> dict[str, Any]:
41
+ """Replace guard exception text with a generic reason for external callers.
42
+
43
+ A guard that breaks its contract records the raw exception text under
44
+ ``checks["guard_<name>"]["error"]``. That detail is valuable in the
45
+ forensic record — which keeps it — but it can carry internal information
46
+ (file paths, hostnames, credentials embedded in a connection URL), so it
47
+ is not returned over the REST API. The check name and its ``ERROR``
48
+ action still tell a caller which guard failed.
49
+ """
50
+ scrubbed: dict[str, Any] = {}
51
+ for name, entry in checks.items():
52
+ if isinstance(entry, dict) and "error" in entry:
53
+ scrubbed[name] = {**entry, "error": "Guard error"}
54
+ else:
55
+ scrubbed[name] = entry
56
+ return scrubbed
57
+
58
+
40
59
  def create_integration_endpoints(
41
60
  *,
42
61
  get_firewall: Any,
@@ -125,7 +144,7 @@ def create_integration_endpoints(
125
144
  return {
126
145
  "action": action,
127
146
  "risk_level": gov.risk_level,
128
- "checks": result.checks,
147
+ "checks": _scrub_check_errors(result.checks),
129
148
  "redacted_content": redacted_content if action == "REDACT" else None,
130
149
  "latency_ms": round(result.latency_ms, 2),
131
150
  }
@@ -112,7 +112,9 @@ class Settings(BaseSettings):
112
112
  # "dry-run": same as observe but additionally tag the response so
113
113
  # downstream tools know the request was analysed.
114
114
  # Restrictive default — opt out explicitly via ADMINA_GOVERNANCE_MODE=observe.
115
- GOVERNANCE_MODE: str = "enforce"
115
+ # Read from ADMINA_GOVERNANCE_MODE (canonical name; the bare GOVERNANCE_MODE
116
+ # env var is not accepted).
117
+ GOVERNANCE_MODE: str = Field(default="enforce", validation_alias="ADMINA_GOVERNANCE_MODE")
116
118
 
117
119
  # Governance thresholds
118
120
  LOOP_WINDOW_SIZE: int = 10
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: admina-framework
3
- Version: 0.11.0
3
+ Version: 0.11.1
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>
@@ -30,7 +30,7 @@ License-File: NOTICE
30
30
  Requires-Dist: pyyaml<7,>=6.0
31
31
  Requires-Dist: click<9,>=8.1
32
32
  Requires-Dist: jinja2<4,>=3.1
33
- Requires-Dist: cryptography<50,>=41.0
33
+ Requires-Dist: cryptography<51,>=41.0
34
34
  Provides-Extra: proxy
35
35
  Requires-Dist: fastapi<1,>=0.104; extra == "proxy"
36
36
  Requires-Dist: uvicorn[standard]<1,>=0.24; extra == "proxy"
@@ -331,16 +331,23 @@ from admina import GovernedModel, GovernedData, GovernedAgent, ComplianceKit
331
331
 
332
332
  | Interface | Builtin implementations |
333
333
  |-----------|------------------------|
334
- | Model Adapter | Ollama, OpenAI |
334
+ | Model Adapter | Ollama, OpenAI, Anthropic, Gemini, Mistral, Bedrock, vLLM |
335
335
  | Data Connector | ChromaDB, Filesystem |
336
336
  | Governance Domain | GuardrailsAI (toxic, jailbreak, bias, PII) |
337
337
  | Compliance Template | EU AI Act |
338
338
  | Transport Adapter | MCP, HTTP REST |
339
339
  | Forensic Store | Filesystem, S3-compatible (boto3 — AWS S3, MinIO, R2, …) |
340
340
  | Auth Provider | API Key |
341
- | PII Engine | spaCy + Regex |
341
+ | PII Engine | spaCy + Regex (default), Microsoft Presidio (`pip install admina-framework[presidio]`, `ADMINA_PII_ENGINE=presidio`) |
342
342
  | Alert Channel | Log, Webhook |
343
343
 
344
+ Model adapters lazy-import their provider SDK, so install the ones you
345
+ use: `pip install admina-framework[adapters]` for all of them, or a
346
+ single provider (`[openai]`, `[ollama]`, `[anthropic]`, `[mistral]`,
347
+ `[gemini]`, `[bedrock]`). vLLM has no extra of its own — it serves an
348
+ OpenAI-compatible API and subclasses the OpenAI adapter, so install
349
+ `[openai]` for it.
350
+
344
351
  ```bash
345
352
  admina plugin list # List registered plugins
346
353
  admina plugin install ./my-plugin # Install a custom plugin
@@ -132,6 +132,7 @@ tests/test_core_config.py
132
132
  tests/test_domains.py
133
133
  tests/test_domains_governance.py
134
134
  tests/test_engines.py
135
+ tests/test_error_disclosure.py
135
136
  tests/test_firewall_parity.py
136
137
  tests/test_forensic_blackbox.py
137
138
  tests/test_gateway_config.py
@@ -144,6 +145,7 @@ tests/test_guard_fail_mode.py
144
145
  tests/test_mcp_transport.py
145
146
  tests/test_presidio_engine.py
146
147
  tests/test_proxy_forensic_would_action.py
148
+ tests/test_proxy_governance_mode_config.py
147
149
  tests/test_proxy_guard_fail_mode.py
148
150
  tests/test_proxy_mcp_response_pii.py
149
151
  tests/test_proxy_plugins.py
@@ -1,7 +1,7 @@
1
1
  pyyaml<7,>=6.0
2
2
  click<9,>=8.1
3
3
  jinja2<4,>=3.1
4
- cryptography<50,>=41.0
4
+ cryptography<51,>=41.0
5
5
 
6
6
  [adapters]
7
7
  admina-framework[anthropic,bedrock,gemini,mistral,ollama,openai]
@@ -19,7 +19,7 @@ build-backend = "setuptools.build_meta"
19
19
 
20
20
  [project]
21
21
  name = "admina-framework"
22
- version = "0.11.0"
22
+ version = "0.11.1"
23
23
  description = "Admina — governed AI development framework"
24
24
  readme = "README.md"
25
25
  requires-python = ">=3.11"
@@ -52,7 +52,7 @@ dependencies = [
52
52
  "pyyaml>=6.0,<7",
53
53
  "click>=8.1,<9",
54
54
  "jinja2>=3.1,<4",
55
- "cryptography>=41.0,<50",
55
+ "cryptography>=41.0,<51",
56
56
  ]
57
57
 
58
58
  [project.urls]
@@ -161,7 +161,7 @@ dev = [
161
161
  # Documentation
162
162
  "mkdocs>=1.6,<2",
163
163
  "mkdocs-material>=9.5,<10",
164
- "mkdocstrings[python]>=0.25,<1",
164
+ "mkdocstrings[python]>=0.25,<2",
165
165
  ]
166
166
 
167
167
  [tool.uv]
@@ -0,0 +1,72 @@
1
+ # Copyright © 2025–2026 Stefano Noferi & Admina contributors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """Exception text must not reach API responses (CodeQL py/stack-trace-exposure).
15
+
16
+ Backend failures and guard crashes are logged server-side and recorded in the
17
+ forensic log with full detail; the HTTP responses carry a generic reason. The
18
+ raw text can embed hosts, ports and credentials from a connection URL.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from admina.proxy.api.integration import _scrub_check_errors
24
+
25
+ # A secret-bearing message of the kind a real backend/guard failure produces.
26
+ _LEAKY = "Connection refused: redis://admin:s3cr3t@internal-cache.corp:6379/0"
27
+
28
+
29
+ class TestValidateResponseScrubsGuardErrors:
30
+ """`/api/v1/validate` must not echo guard exception text to the caller."""
31
+
32
+ def test_guard_error_text_is_replaced(self):
33
+ scrubbed = _scrub_check_errors({"guard_boom": {"action": "ERROR", "error": _LEAKY}})
34
+ assert scrubbed["guard_boom"]["error"] == "Guard error"
35
+ assert "s3cr3t" not in str(scrubbed)
36
+ assert "internal-cache.corp" not in str(scrubbed)
37
+
38
+ def test_which_guard_failed_is_still_reported(self):
39
+ """Scrubbing keeps the diagnostic signal: name + ERROR action."""
40
+ scrubbed = _scrub_check_errors({"guard_boom": {"action": "ERROR", "error": _LEAKY}})
41
+ assert "guard_boom" in scrubbed
42
+ assert scrubbed["guard_boom"]["action"] == "ERROR"
43
+
44
+ def test_non_error_checks_pass_through_untouched(self):
45
+ checks = {
46
+ "injection_firewall": {"is_injection": False, "risk_level": "none"},
47
+ "pii_redaction": {"count": 2},
48
+ }
49
+ assert _scrub_check_errors(checks) == checks
50
+
51
+ def test_does_not_mutate_the_caller_dict(self):
52
+ """The forensic record shares this dict — it must keep the full text."""
53
+ original = {"guard_boom": {"action": "ERROR", "error": _LEAKY}}
54
+ _scrub_check_errors(original)
55
+ assert original["guard_boom"]["error"] == _LEAKY
56
+
57
+
58
+ class TestDashboardHealthScrubsBackendErrors:
59
+ """The dashboard services endpoint reports failure without the exception."""
60
+
61
+ def test_source_returns_generic_reason_not_exception_text(self):
62
+ """Redis/ClickHouse handlers must not put `str(exc)` in the payload."""
63
+ import inspect
64
+
65
+ from admina.proxy.api import dashboard
66
+
67
+ source = inspect.getsource(dashboard)
68
+ # The health handlers build their payload with a fixed string; the
69
+ # exception itself goes to logger.warning instead.
70
+ assert '"status": "unhealthy", "error": "Health check failed"' in source
71
+ assert '"error": "Health check failed",' in source
72
+ assert '"error": str(exc)' not in source
@@ -0,0 +1,56 @@
1
+ # Copyright © 2025–2026 Stefano Noferi & Admina contributors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Settings reads the governance mode from the canonical ADMINA_ env var.
16
+
17
+ Exercises the real ``Settings`` class (not a SimpleNamespace double) with a
18
+ patched environment: ``Settings`` declares no ``env_prefix``, so without an
19
+ explicit ``validation_alias`` the documented ``ADMINA_GOVERNANCE_MODE`` name
20
+ was silently ignored (``extra="ignore"``).
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import pytest
26
+
27
+
28
+ class TestGovernanceModeConfig:
29
+ def test_default_is_enforce(self):
30
+ from admina.proxy.config import Settings
31
+
32
+ s = Settings(_env_file=None)
33
+ assert s.GOVERNANCE_MODE == "enforce"
34
+
35
+ def test_reads_canonical_env_var(self, monkeypatch):
36
+ monkeypatch.setenv("ADMINA_GOVERNANCE_MODE", "OBSERVE")
37
+ from admina.proxy.config import Settings
38
+
39
+ s = Settings(_env_file=None)
40
+ assert s.GOVERNANCE_MODE == "observe"
41
+
42
+ def test_dry_run_underscore_normalized(self, monkeypatch):
43
+ monkeypatch.setenv("ADMINA_GOVERNANCE_MODE", "dry_run")
44
+ from admina.proxy.config import Settings
45
+
46
+ s = Settings(_env_file=None)
47
+ assert s.GOVERNANCE_MODE == "dry-run"
48
+
49
+ def test_invalid_value_rejected(self, monkeypatch):
50
+ from pydantic import ValidationError
51
+
52
+ from admina.proxy.config import Settings
53
+
54
+ monkeypatch.setenv("ADMINA_GOVERNANCE_MODE", "maybe")
55
+ with pytest.raises(ValidationError):
56
+ Settings(_env_file=None)