diff --git a/.env.example b/.env.example
index dc4fd60..1cfa011 100644
--- a/.env.example
+++ b/.env.example
@@ -122,7 +122,7 @@ GRAFANA_ADMIN_PASSWORD=
# PII detection engine: spacy-regex (default) | presidio | the name of an
# engine another package registers in the admina.pii_engines entry-point group.
-# presidio requires: pip install "admina-framework[presidio]"
+# presidio requires: pip install "admina[presidio]"
# ADMINA_PII_ENGINE=spacy-regex
# PII masks: typed (default: [EMAIL], [PERSON], ...) | omissis ([OMISSIS] for
diff --git a/.github/workflows/release-core.yml b/.github/workflows/release-core.yml
index 809e576..7058669 100644
--- a/.github/workflows/release-core.yml
+++ b/.github/workflows/release-core.yml
@@ -29,7 +29,7 @@
# Workflow name: release-core.yml (this file)
# Environment name: pypi-core
#
-# The matching trusted publisher for admina-framework is configured for
+# The matching trusted publisher for admina is configured for
# release.yml (the other workflow).
#
# ── How to cut a release ───────────────────────────────────────────────────
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a0f28c9..64e9cfd 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -14,10 +14,12 @@
# Release pipeline — fires on version tags (vX.Y.Z).
#
-# Publishes the pure-Python root package admina-framework to PyPI, then the
-# alias package admina (packaging/admina: no code, it installs
-# admina-framework at the same version), and creates the GitHub Release. The Rust accelerator admina-core is built
-# and published by a sibling workflow (.github/workflows/release-core.yml)
+# Publishes the pure-Python root package admina to PyPI and creates the
+# GitHub Release. On the v0.14.0 tag it also publishes the last
+# admina-framework release (packaging/admina-framework, built by
+# scripts/build-admina-framework-sdist.py): a source distribution that stops
+# its installation with the commands to switch to admina. The Rust
+# accelerator admina-core is built and published by a sibling workflow (.github/workflows/release-core.yml)
# triggered by the same tag — they run in parallel, independently.
#
# Why two workflows? PyPI Trusted Publishers had a transient issue
@@ -29,15 +31,15 @@
# Before the first run, configure the publisher on pypi.org:
#
# https://pypi.org/manage/account/publishing/ → Add pending publisher
-# PyPI Project Name: admina-framework
+# PyPI Project Name: admina
# Owner: admina-org
# Repository name: admina
# Workflow name: release.yml
# Environment name: pypi
#
-# The publisher of the alias project "admina" has the same values, with
-# PyPI Project Name: admina. The matching publisher for admina-core is
-# configured for release-core.yml.
+# The publisher of the project "admina-framework" has the same values, with
+# PyPI Project Name: admina-framework. The matching publisher for
+# admina-core is configured for release-core.yml.
# See https://docs.pypi.org/trusted-publishers/ for details.
#
# ── How to cut a release ───────────────────────────────────────────────────
@@ -105,9 +107,10 @@ jobs:
run: |
uv build --out-dir dist/
- - name: Build the admina alias (sdist + wheel)
+ - name: Build the last admina-framework release (sdist)
+ if: github.ref_name == 'v0.14.0'
run: |
- uv build packaging/admina --out-dir dist-alias/
+ python3 scripts/build-admina-framework-sdist.py dist-framework/
- name: Upload artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
@@ -117,17 +120,18 @@ jobs:
if-no-files-found: error
retention-days: 7
- - name: Upload alias artifact
+ - name: Upload admina-framework artifact
+ if: github.ref_name == 'v0.14.0'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
- name: admina-alias-dist
- path: dist-alias/*
+ name: admina-framework-dist
+ path: dist-framework/*
if-no-files-found: error
retention-days: 7
- # ── 4. Publish root admina-framework to PyPI ────────────────────────────
+ # ── 4. Publish root admina to PyPI ──────────────────────────────────────
publish-root:
- name: Publish admina-framework to PyPI
+ name: Publish admina to PyPI
needs: [build-root, tests]
# admina-core (the optional Rust accelerator) is published by the
# sibling workflow release-core.yml, in parallel with this one.
@@ -136,7 +140,7 @@ jobs:
runs-on: ubuntu-latest
environment:
name: pypi
- url: https://pypi.org/project/admina-framework/
+ url: https://pypi.org/project/admina/
steps:
- name: Download root artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
@@ -153,20 +157,20 @@ jobs:
packages-dir: dist/
skip-existing: true
- # ── 5. Publish the admina alias to PyPI ─────────────────────────────────
- publish-alias:
- name: Publish admina (alias) to PyPI
- # After admina-framework, so that the version the alias pins exists.
+ # ── 5. Publish the last admina-framework release (v0.14.0 only) ─────────
+ publish-framework-final:
+ name: Publish the last admina-framework release to PyPI
+ if: github.ref_name == 'v0.14.0'
needs: [build-root, tests, publish-root]
runs-on: ubuntu-latest
environment:
name: pypi
- url: https://pypi.org/project/admina/
+ url: https://pypi.org/project/admina-framework/
steps:
- - name: Download alias artifacts
+ - name: Download admina-framework artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
- name: admina-alias-dist
+ name: admina-framework-dist
path: dist
- name: List artifacts
@@ -188,7 +192,7 @@ jobs:
with:
fetch-depth: 0 # needed to extract the CHANGELOG section for this tag
- - name: Download admina-framework artifacts
+ - name: Download admina artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: admina-root-dist
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8b1f4ad..7fb8cd9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,40 @@ stability commitment. See [ROADMAP.md](ROADMAP.md) for planned milestones.
## [Unreleased]
+## [0.14.0] — 2026-10-07
+
+Minor release with a declared breaking change: Admina is published on PyPI
+as `admina`. The module (`import admina`), the `admina` command, the extras,
+`admina-core` and the container images do not change. Upgrading an
+installation of `admina-framework`: see `docs/guides/package-name.md`.
+
+### Changed
+
+- **Breaking:** the distribution is named `admina` (`pip install admina`,
+ `pip install "admina[proxy]"`). `admina-framework` 0.14.0 is its last
+ release: a source distribution that stops the installation with the
+ commands to switch (`pip uninstall -y admina admina-framework && pip
+ install admina`) and leaves the installed packages as they are. A pin
+ such as `admina-framework<0.14` keeps installing the 0.13 releases.
+- The `admina` package holds the code; in 0.13.2 it was an alias that
+ installed `admina-framework`.
+- The `[rust]` extra requires `admina-core>=0.14.0,<0.15`.
+- The `pyproject.toml` that `admina plugin create` writes depends on
+ `admina>=
@@ -80,7 +80,7 @@
| Audit trail | logs you hope nobody deletes | **SHA-256 hash chain** — tamper-evident by design |
| Adding governance to existing code | rewrite the call sites | **Zero code changes** via proxy, or 3 lines via SDK |
| Performance overhead | unknown | **Measured** — engine microbenchmarks and a gateway benchmark to run on your hardware ([Performance](#performance--hybrid-python--rust-engine)) |
-| License | varies | **Apache 2.0**, open core |
+| License | varies | **Apache 2.0** |
> Admina is **decision-support and defense-in-depth**, not legal advice. See [Compliance scope](#compliance-scope) for the full disclaimer and limitations.
@@ -117,52 +117,58 @@ report = kit.gap_analysis(risk_category="high", current_compliance={...})
### Install from PyPI
+> **Package name since 0.14.0.** Admina is published as `admina`; up to
+> 0.13.x it was `admina-framework`, which is no longer released. The module,
+> the `admina` command and the extras did not change. To upgrade an
+> installation of `admina-framework`, see
+> [The `admina` package name](https://github.com/admina-org/admina/blob/main/docs/guides/package-name.md).
+
```bash
# Recommended for new users: SDK + proxy + dashboard.
# Lets you run `admina dev` and see the dashboard out of the box.
-pip install "admina-framework[proxy]"
+pip install "admina[proxy]"
# Everything (proxy + NLP + telemetry). Use this if you also want
# spaCy-based NER for PII detection or OpenTelemetry export.
-pip install "admina-framework[full]"
+pip install "admina[full]"
python -m spacy download en_core_web_sm # for [full] only
# Model-adapter provider SDKs (per-provider extras):
-pip install "admina-framework[openai]" # openai>=1.0
-pip install "admina-framework[ollama]" # ollama>=0.3
-pip install "admina-framework[anthropic]" # anthropic>=0.39
-pip install "admina-framework[mistral]" # mistralai>=1.0
-pip install "admina-framework[gemini]" # google-genai>=1.0
-pip install "admina-framework[bedrock]" # boto3>=1.34 (AWS Bedrock)
+pip install "admina[openai]" # openai>=1.0
+pip install "admina[ollama]" # ollama>=0.3
+pip install "admina[anthropic]" # anthropic>=0.39
+pip install "admina[mistral]" # mistralai>=1.0
+pip install "admina[gemini]" # google-genai>=1.0
+pip install "admina[bedrock]" # boto3>=1.34 (AWS Bedrock)
# All provider SDKs at once:
-pip install "admina-framework[adapters]"
+pip install "admina[adapters]"
# Everything (proxy + NLP + telemetry + all adapters):
-pip install "admina-framework[all]"
+pip install "admina[all]"
python -m spacy download en_core_web_sm # for [all] only
# Optional: Rust-accelerated engine (auto-detected at runtime).
# Opt-in extra — pulls in the admina-core wheel from PyPI.
-pip install "admina-framework[rust]"
+pip install "admina[rust]"
# The proxy for the OpenAI-compatible gateway only: without Redis,
# ClickHouse, boto3 and the scientific stack (see "Embedded deployment").
-pip install "admina-framework[proxy-minimal]"
+pip install "admina[proxy-minimal]"
# Advanced: SDK only (no proxy, no dashboard, no `admina dev`).
# Use this when embedding the SDK into another service and you don't
# need the local dev server.
-pip install admina-framework
+pip install admina
```
-> The PyPI distribution name is `admina-framework`; the Python import
+> The PyPI distribution name is `admina`; the Python import
> name is `admina` (e.g. `from admina import GovernedModel`). This is
> a normal Python pattern — same as `python-dateutil` → `import dateutil`.
> The Rust engine is an **optional, opt-in** accelerator. The default
-> `pip install admina-framework` ships only the pure-Python implementation;
-> `admina-framework[rust]` adds the `admina-core` wheel, which Admina
+> `pip install admina` ships only the pure-Python implementation;
+> `admina[rust]` adds the `admina-core` wheel, which Admina
> auto-detects at runtime: under `ADMINA_ENGINE=auto` (the default) the
> firewall and the loop breaker run on Rust whenever it is installed, as in
> the official proxy image (see [Engine selection](#engine-selection)).
@@ -174,11 +180,6 @@ pip install admina-framework
> matters more than that extra coverage. See
> [Performance](#performance--hybrid-python--rust-engine) for the trade-off.
-The PyPI package `admina` is an alias: `pip install admina` installs
-`admina-framework` at the same version, and `admina[X]` installs
-`admina-framework[X]` for every extra above. It has no code of its own, so
-both names install the same `admina` module.
-
### Or install from source
```bash
@@ -272,11 +273,11 @@ from admina import GovernedModel, GovernedData, GovernedAgent, ComplianceKit
| Transport Adapter | MCP, HTTP REST |
| Forensic Store | Filesystem, S3-compatible (boto3 — AWS S3, MinIO, R2, …) |
| Auth Provider | API Key |
-| PII Engine | spaCy + Regex (default), Microsoft Presidio (`pip install admina-framework[presidio]`, `ADMINA_PII_ENGINE=presidio`); engines of other packages through the `admina.pii_engines` entry-point group (see [PII engines](#pii-engines)) |
+| PII Engine | spaCy + Regex (default), Microsoft Presidio (`pip install admina[presidio]`, `ADMINA_PII_ENGINE=presidio`); engines of other packages through the `admina.pii_engines` entry-point group (see [PII engines](#pii-engines)) |
| Alert Channel | Log, Webhook |
Model adapters lazy-import their provider SDK, so install the ones you
-use: `pip install admina-framework[adapters]` for all of them, or a
+use: `pip install admina[adapters]` for all of them, or a
single provider (`[openai]`, `[ollama]`, `[anthropic]`, `[mistral]`,
`[gemini]`, `[bedrock]`). vLLM has no extra of its own — it serves an
OpenAI-compatible API and subclasses the OpenAI adapter, so install
@@ -472,7 +473,7 @@ that only the Python firewall applies: `agent_security.firewall`
`pattern_packs` (an empty list is not set). The error names the cause:
```
-ADMINA_ENGINE=rust, but admina-core is not installed: install admina-framework[rust], or set ADMINA_ENGINE=python (or auto) to run the Python engines
+ADMINA_ENGINE=rust, but admina-core is not installed: install admina[rust], or set ADMINA_ENGINE=python (or auto) to run the Python engines
ADMINA_ENGINE=rust, but admina.yaml sets agent_security.firewall.pattern_packs, which only the Python firewall applies: remove them, or set ADMINA_ENGINE=python (or auto) to run the Python firewall
```
@@ -976,7 +977,7 @@ attempt. The `proxy-minimal` extra installs the proxy without Redis,
ClickHouse, boto3, typer and the scientific stack of the Python loop breaker:
```bash
-pip install "admina-framework[proxy-minimal]"
+pip install "admina[proxy-minimal]"
ADMINA_ENABLED_SURFACES=gateway REDIS_URL= CLICKHOUSE_HOST= \
ADMINA_API_KEY_FILE=/run/secrets/admina_api_key \
uvicorn admina.proxy.main:app --host 0.0.0.0 --port 8080
@@ -1670,7 +1671,7 @@ cd integrations/cheshirecat/admina-plugin
Governs every LLM call and tool invocation in-process. Install
-`admina-framework[proxy,nlp]`: the loop detection that the callbacks turn
+`admina[proxy,nlp]`: the loop detection that the callbacks turn
on by default needs scikit-learn from `[proxy]` (or pass
`loop_detection=False`).
@@ -1702,9 +1703,9 @@ See [full integration docs](https://github.com/admina-org/admina/blob/main/docs/
## Performance — Hybrid Python + Rust engine
The Rust core engine is an optional accelerator. The default
-`pip install admina-framework` ships only the pure-Python implementation;
+`pip install admina` ships only the pure-Python implementation;
enable the Rust engine with the opt-in extra `pip install
-"admina-framework[rust]"` (or build from source for local development —
+"admina[rust]"` (or build from source for local development —
`maturin develop --release --manifest-path core-rust/Cargo.toml`, see
[CONTRIBUTING.md](https://github.com/admina-org/admina/blob/main/CONTRIBUTING.md)). Under `ADMINA_ENGINE=auto` Admina
runs the Rust firewall and loop breaker when the extension is installed and
@@ -1934,7 +1935,7 @@ guard error under `ADMINA_GUARD_FAIL_MODE=closed`) or `response_blocked`
- [CONTRIBUTING.md](https://github.com/admina-org/admina/blob/main/CONTRIBUTING.md) — development setup, testing, and pull request workflow
- [MODEL_CARD.md](https://github.com/admina-org/admina/blob/main/MODEL_CARD.md) — transparency artifact for every Admina governance component (intended use, scope, limitations, known failure modes), aligned with EU AI Act Art. 13 and NIST AI RMF
-- [ROADMAP.md](https://github.com/admina-org/admina/blob/main/ROADMAP.md) — planned milestones from 0.9.x to 1.0 and beyond
+- [ROADMAP.md](https://github.com/admina-org/admina/blob/main/ROADMAP.md) — released milestones and the next planned release
- [CHANGELOG.md](https://github.com/admina-org/admina/blob/main/CHANGELOG.md) — release notes
- [SECURITY.md](https://github.com/admina-org/admina/blob/main/SECURITY.md) — coordinated disclosure policy
- [CODE_OF_CONDUCT.md](https://github.com/admina-org/admina/blob/main/CODE_OF_CONDUCT.md) — Contributor Covenant 2.1
diff --git a/ROADMAP.md b/ROADMAP.md
index 917f037..956e733 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -6,7 +6,7 @@ not on a calendar. Scope may shift in response to user feedback, security
findings, or upstream changes in the governance landscape (EU AI Act
implementing acts, new frameworks, new attack classes).
-The current release is **0.13.2**. Admina is pre-1.0: the public API may
+The current release is **0.14.0**. Admina is pre-1.0: the public API may
still evolve before the 1.0 stability commitment, so a minor release may
carry a declared breaking change once its replacement is in place. Shipped
detail lives in [CHANGELOG.md](CHANGELOG.md).
@@ -130,85 +130,14 @@ deployment, and a forensic store that can be verified record by record.
---
-## 0.14.0 — Compliance template expansion
+## 0.14.0 — Package name
-Beyond the EU AI Act.
-
-- NIS2 template (incident response, supply-chain obligations)
-- ISO / IEC 42001 template (AI management system controls)
-- SOC 2 template (Trust Services Criteria mapping)
-- Cross-framework gap analysis: surface obligations that satisfy
- multiple frameworks in a single control
-- Report export in PDF and DOCX, signed with the forensic key
-
----
-
-## Not yet scheduled
-
-Planned, without a release assigned yet.
-
-**Observability**
-
-- Emission of the streaming-request metadata shaped in 0.11 onto the
- OpenTelemetry GenAI semantic conventions (`gen_ai.request.model`,
- `gen_ai.usage.*`, `gen_ai.response.finish_reasons`,
- `gen_ai.client.operation.duration`) — no metadata field is renamed at
- the emission boundary.
-- An SLO panel on the Prometheus metrics.
-- Structured error taxonomy: stable error codes across proxy, SDK, and
- REST API.
-- Benchmark regression gate in CI (fail on a >10% regression versus
- baseline).
-- Tracing correlation from the SDK through the proxy to the upstream LLM
- (the gateway already records W3C trace context).
-
-**Multi-tenancy and RBAC** — operating Admina as a shared service.
-
-- Organisation / workspace isolation in the proxy
-- Per-tenant quotas (request rate, forensic retention, compliance
- templates enabled)
-- Role-based access control on proxy endpoints (read / write / admin)
-- OIDC authentication provider as a built-in plugin
-- Shared async pool for data connectors; decision cache for the injection
- firewall fast path.
-- Per-tenant forensic namespace with independent hash chains
-
----
-
-## 1.0.0 — API freeze and long-term support
-
-The stability commitment. Shipped when the public surface has settled
-through real-world use.
-
-- Plugin ABI v1 frozen with contract tests; third-party plugin
- certification suite
-- Official client SDKs: TypeScript, Go
-- Deprecation policy formalised; 18-month LTS window for the 1.0 line
-- Security advisory process documented; CVE assignment workflow
-- Removal of the pre-0.3.0 compatibility shims in `proxy/`
-
----
-
-## 1.1.0 — Horizontal scale
-
-Running Admina as stateless, horizontally-scaled infrastructure.
-
-- Stateless proxy mode backed by shared Redis / ClickHouse
-- Hot-reload of governance configuration without restart
-- Official Helm chart and Kubernetes operator
-- Cross-region federation for the forensic store
-
----
-
-## 2.0.0 — Only if required
-
-Reserved for breaking changes that cannot be delivered under 1.x.
-No breaking changes are planned. Candidate drivers:
-
-- Plugin ABI v2 if real-world use reveals design limitations that cannot be
- extended under v1
-- Streaming-first pipeline rearchitecture if chunk-level governance
- becomes the dominant workload
+- Admina is published on PyPI as `admina`; `admina-framework` is no longer
+ released after a final 0.14.0 that stops the installation with the
+ commands to switch. A declared breaking change for installs of
+ `admina-framework`: the module, the `admina` command and the extras do
+ not change. See
+ [docs/guides/package-name.md](docs/guides/package-name.md).
---
diff --git a/SECURITY.md b/SECURITY.md
index 9e83c56..2a92bd5 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -4,8 +4,8 @@
| Version | Supported |
|---------|-----------|
-| 0.13.x | Yes |
-| < 0.13 | No |
+| 0.14.x | Yes |
+| < 0.14 | No |
During the pre-1.0 phase only the latest minor line receives security
fixes. Once 1.0 ships, an LTS window will be defined in
diff --git a/admina/__init__.py b/admina/__init__.py
index ab5a834..a9e5ab0 100644
--- a/admina/__init__.py
+++ b/admina/__init__.py
@@ -23,7 +23,7 @@
from admina.sdk import ComplianceKit, GovernedAgent, GovernedData, GovernedModel
-__version__ = "0.13.2"
+__version__ = "0.14.0"
__all__ = [
"__version__",
diff --git a/admina/cli/main.py b/admina/cli/main.py
index ff2c1c8..4aef347 100644
--- a/admina/cli/main.py
+++ b/admina/cli/main.py
@@ -300,7 +300,7 @@ def _format_next_steps(project_name: str) -> str:
[
"",
" To run the local proxy + dashboard (admina dev), install the [proxy] extra:",
- " pip install 'admina-framework[proxy]' --upgrade",
+ " pip install 'admina[proxy]' --upgrade",
]
)
if docker_ok:
@@ -555,11 +555,11 @@ def _require_proxy_extra_for_local_dev() -> None:
click.echo(" admina dev (local mode) requires the [proxy] extra.", err=True)
click.echo(" Install one of:", err=True)
click.echo(
- " pip install 'admina-framework[proxy]' --upgrade",
+ " pip install 'admina[proxy]' --upgrade",
err=True,
)
click.echo(
- " pip install 'admina-framework[full]' --upgrade # adds NLP + telemetry",
+ " pip install 'admina[full]' --upgrade # adds NLP + telemetry",
err=True,
)
click.echo("", err=True)
@@ -1226,11 +1226,11 @@ def doctor() -> None:
if extras_status.get("proxy") != "ok":
click.echo(
f" {warn_mark} admina dev (local mode) needs the [proxy] extra — "
- "pip install 'admina-framework[proxy]' --upgrade"
+ "pip install 'admina[proxy]' --upgrade"
)
issues.append(
"admina dev (local mode) requires the [proxy] extra — "
- "run: pip install 'admina-framework[proxy]' --upgrade"
+ "run: pip install 'admina[proxy]' --upgrade"
)
# ── spaCy NER model ──────────────────────────────────────
@@ -1736,8 +1736,7 @@ def configure(output: Path, non_interactive: bool) -> None:
to disable, loop-breaker thresholds, PII categories.
Defaults are restrictive: enforce mode, all firewall categories on,
- EU-aware PII set on. The wizard never recommends a "Pro" upgrade
- or a paid feature — the OSS edition is fully usable as-is.
+ EU-aware PII set on.
"""
if output.exists():
diff --git a/admina/cli/templates/plugin_pyproject.toml.j2 b/admina/cli/templates/plugin_pyproject.toml.j2
index efa238e..fa239c0 100644
--- a/admina/cli/templates/plugin_pyproject.toml.j2
+++ b/admina/cli/templates/plugin_pyproject.toml.j2
@@ -8,10 +8,10 @@ version = "0.1.0"
description = "Admina {{ plugin_type.replace('_', ' ') }} plugin: {{ plugin_name }}"
requires-python = ">=3.11"
dependencies = [
- # Floor pinned to the admina-framework version that generated this
+ # Floor pinned to the admina version that generated this
# scaffold: the plugin contract (class-attr name, async ABC methods)
# requires at least that runtime.
- "admina-framework>={{ admina_version }}",
+ "admina>={{ admina_version }}",
]
[project.entry-points."admina.plugins"]
diff --git a/admina/domains/compliance/gdpr.py b/admina/domains/compliance/gdpr.py
index dd7b286..2977d2a 100644
--- a/admina/domains/compliance/gdpr.py
+++ b/admina/domains/compliance/gdpr.py
@@ -23,7 +23,7 @@
this release.
- :func:`render_dpia_template` — Art. 35 DPIA scaffold rendered
- as Markdown from the operator's input. The OSS module produces
+ as Markdown from the operator's input. The module produces
a *blank template populated with the operator's facts* — it is
NOT a guided wizard, it does NOT score or recommend mitigations,
and it is NOT legal advice. A real DPIA always involves the DPO
diff --git a/admina/domains/compliance/nis2.py b/admina/domains/compliance/nis2.py
index a75e93f..afc4323 100644
--- a/admina/domains/compliance/nis2.py
+++ b/admina/domains/compliance/nis2.py
@@ -18,7 +18,7 @@
(EU) 2022/2555) Art. 21 cybersecurity risk-management measures and
Art. 23 incident reporting.
-Scope of this OSS module: a *triage tool*. It enumerates the ten
+Scope of this module: a *triage tool*. It enumerates the ten
measure areas required by Art. 21 and lets the operator declare for
each one which of a small number of standard controls is in place,
producing a coverage score and a list of gaps.
diff --git a/admina/domains/data_sovereignty/pii.py b/admina/domains/data_sovereignty/pii.py
index 688ff2a..1629245 100644
--- a/admina/domains/data_sovereignty/pii.py
+++ b/admina/domains/data_sovereignty/pii.py
@@ -208,7 +208,7 @@ def __init__(self, config=None, *, mask_style: str = "typed"):
if _spacy is None:
logger.info(
"spaCy not installed — PII redaction running in regex-only mode "
- "(install admina-framework[nlp] for NER-based detection)"
+ "(install admina[nlp] for NER-based detection)"
)
self.nlp = None
else:
diff --git a/admina/engines/__init__.py b/admina/engines/__init__.py
index 989da75..7558aac 100644
--- a/admina/engines/__init__.py
+++ b/admina/engines/__init__.py
@@ -129,7 +129,7 @@ def _require_rust() -> None:
if not _rust_available:
raise EngineSelectionError(
"ADMINA_ENGINE=rust, but admina-core is not installed: install "
- "admina-framework[rust], or set ADMINA_ENGINE=python (or auto) to run "
+ "admina[rust], or set ADMINA_ENGINE=python (or auto) to run "
"the Python engines"
)
@@ -458,7 +458,7 @@ def __init__(self, **kwargs):
except ImportError as exc:
raise ImportError(
"The Python loop breaker needs numpy and scikit-learn: "
- "pip install 'admina-framework[proxy]' (or 'admina-framework[rust]' "
+ "pip install 'admina[proxy]' (or 'admina[rust]' "
"for the Rust loop breaker)"
) from exc
diff --git a/admina/engines/presidio.py b/admina/engines/presidio.py
index df53f20..60aa591 100644
--- a/admina/engines/presidio.py
+++ b/admina/engines/presidio.py
@@ -36,7 +36,7 @@
E-mail domains are checked against the public suffix list bundled with
tldextract, with no cache and no download, so the engine makes no network
access. Presidio is an optional extra:
- pip install 'admina-framework[presidio]'
+ pip install 'admina[presidio]'
"""
from __future__ import annotations
@@ -240,7 +240,7 @@ def __init__(
except ImportError as exc:
raise ImportError(
"The Presidio PII engine requires the [presidio] extra. Install it with "
- "`pip install 'admina-framework[presidio]'`."
+ "`pip install 'admina[presidio]'`."
) from exc
pipelines = _pipelines(nlp_models)
diff --git a/admina/integrations/_engines.py b/admina/integrations/_engines.py
index e3dd563..b84d059 100644
--- a/admina/integrations/_engines.py
+++ b/admina/integrations/_engines.py
@@ -74,8 +74,8 @@ def get_loop_breaker():
raise ImportError(
"Loop detection (loop_detection=True, the default of the "
"LangChain and CrewAI callbacks) needs numpy and scikit-learn: "
- "pip install 'admina-framework[proxy]' (or "
- "'admina-framework[rust]' for the Rust loop breaker), or pass "
+ "pip install 'admina[proxy]' (or "
+ "'admina[rust]' for the Rust loop breaker), or pass "
"loop_detection=False"
) from exc
return _loop_breaker
diff --git a/admina/integrations/crewai/README.md b/admina/integrations/crewai/README.md
index 3b1c0a1..8b9ca94 100644
--- a/admina/integrations/crewai/README.md
+++ b/admina/integrations/crewai/README.md
@@ -9,7 +9,7 @@ pip install -e ".[proxy,nlp]" # Admina: loop breaker (numpy, scikit-learn) + N
pip install crewai # Your CrewAI deps
```
-From PyPI: `pip install "admina-framework[proxy,nlp]"`. Loop detection is on
+From PyPI: `pip install "admina[proxy,nlp]"`. Loop detection is on
by default and needs numpy and scikit-learn (`[proxy]`), or the Rust loop
breaker (`[rust]`); without either, pass `loop_detection=False`.
diff --git a/admina/integrations/langchain/README.md b/admina/integrations/langchain/README.md
index dd620aa..8911741 100644
--- a/admina/integrations/langchain/README.md
+++ b/admina/integrations/langchain/README.md
@@ -9,7 +9,7 @@ pip install -e ".[proxy,nlp]" # Admina: loop breaker (numpy, scikit-learn) + N
pip install langchain # Your LangChain deps
```
-From PyPI: `pip install "admina-framework[proxy,nlp]"`. Loop detection is on
+From PyPI: `pip install "admina[proxy,nlp]"`. Loop detection is on
by default and needs numpy and scikit-learn (`[proxy]`), or the Rust loop
breaker (`[rust]`); without either, pass `loop_detection=False`.
diff --git a/admina/plugins/builtin/adapters/anthropic.py b/admina/plugins/builtin/adapters/anthropic.py
index 7e26a39..7c51c6d 100644
--- a/admina/plugins/builtin/adapters/anthropic.py
+++ b/admina/plugins/builtin/adapters/anthropic.py
@@ -17,7 +17,7 @@
Wraps the ``anthropic`` Python client (sync) to provide inference through
the Anthropic Messages API.
-Requires: ``pip install 'admina-framework[anthropic]'`` (optional dependency).
+Requires: ``pip install 'admina[anthropic]'`` (optional dependency).
"""
from __future__ import annotations
@@ -74,7 +74,7 @@ def _get_client(self) -> Any:
except ImportError as exc:
raise ImportError(
"The 'anthropic' package is required for AnthropicAdapter. "
- "Install it with: pip install 'admina-framework[anthropic]'"
+ "Install it with: pip install 'admina[anthropic]'"
) from exc
kwargs: dict[str, Any] = {}
if self._api_key:
diff --git a/admina/plugins/builtin/adapters/bedrock.py b/admina/plugins/builtin/adapters/bedrock.py
index c1606a0..97a300d 100644
--- a/admina/plugins/builtin/adapters/bedrock.py
+++ b/admina/plugins/builtin/adapters/bedrock.py
@@ -18,7 +18,7 @@
Converse API. Authentication follows the standard AWS credential chain
(environment variables, ``~/.aws/credentials``, IAM instance role, etc.).
-Requires: ``pip install 'admina-framework[bedrock]'`` (optional dependency).
+Requires: ``pip install 'admina[bedrock]'`` (optional dependency).
"""
from __future__ import annotations
@@ -80,7 +80,7 @@ def _get_client(self) -> Any:
except ImportError as exc:
raise ImportError(
"The 'boto3' package is required for BedrockAdapter. "
- "Install it with: pip install 'admina-framework[bedrock]'"
+ "Install it with: pip install 'admina[bedrock]'"
) from exc
self._client = boto3.client("bedrock-runtime", region_name=self._region)
return self._client
diff --git a/admina/plugins/builtin/adapters/gemini.py b/admina/plugins/builtin/adapters/gemini.py
index 3cd0df9..5e80a4d 100644
--- a/admina/plugins/builtin/adapters/gemini.py
+++ b/admina/plugins/builtin/adapters/gemini.py
@@ -17,7 +17,7 @@
Wraps the ``google-genai`` Python client (sync) to provide inference through
the Google Gemini GenerateContent API.
-Requires: ``pip install 'admina-framework[gemini]'`` (optional dependency).
+Requires: ``pip install 'admina[gemini]'`` (optional dependency).
"""
from __future__ import annotations
@@ -70,7 +70,7 @@ def _get_client(self) -> Any:
except ImportError as exc:
raise ImportError(
"The 'google-genai' package is required for GeminiAdapter. "
- "Install it with: pip install 'admina-framework[gemini]'"
+ "Install it with: pip install 'admina[gemini]'"
) from exc
kwargs: dict[str, Any] = {}
if self._api_key:
diff --git a/admina/plugins/builtin/adapters/mistral.py b/admina/plugins/builtin/adapters/mistral.py
index aa570e1..de982aa 100644
--- a/admina/plugins/builtin/adapters/mistral.py
+++ b/admina/plugins/builtin/adapters/mistral.py
@@ -17,7 +17,7 @@
Wraps the ``mistralai`` Python client (sync) to provide inference through
the Mistral Chat Completions API.
-Requires: ``pip install 'admina-framework[mistral]'`` (optional dependency).
+Requires: ``pip install 'admina[mistral]'`` (optional dependency).
"""
from __future__ import annotations
@@ -70,7 +70,7 @@ def _get_client(self) -> Any:
except ImportError as exc:
raise ImportError(
"The 'mistralai' package is required for MistralAdapter. "
- "Install it with: pip install 'admina-framework[mistral]'"
+ "Install it with: pip install 'admina[mistral]'"
) from exc
kwargs: dict[str, Any] = {}
if self._api_key:
diff --git a/admina/proxy/main.py b/admina/proxy/main.py
index c9787f5..d5182cf 100644
--- a/admina/proxy/main.py
+++ b/admina/proxy/main.py
@@ -485,7 +485,7 @@ def _build_loop_breaker() -> Any:
raise RuntimeError(
"The mcp and integration surfaces need the loop breaker, whose Python "
f"engine needs numpy and scikit-learn ({exc}). Install "
- "admina-framework[proxy] (or admina-framework[rust]), or serve only the "
+ "admina[proxy] (or admina[rust]), or serve only the "
"gateway: ADMINA_ENABLED_SURFACES=gateway."
) from exc
@@ -548,7 +548,7 @@ async def _connect_redis(url: str) -> Any:
except ImportError:
logger.warning(
"REDIS_URL is set but the redis package is not installed "
- "(pip install 'admina-framework[proxy]') — continuing without rate-limit cache"
+ "(pip install 'admina[proxy]') — continuing without rate-limit cache"
)
return None
try:
@@ -573,7 +573,7 @@ def _connect_clickhouse() -> Any:
except ImportError:
logger.warning(
"CLICKHOUSE_HOST is set but clickhouse-connect is not installed "
- "(pip install 'admina-framework[proxy]') — analytics disabled"
+ "(pip install 'admina[proxy]') — analytics disabled"
)
return None
try:
@@ -1659,12 +1659,6 @@ def _emit(section: str, obj: Any, prefix: str = "") -> None:
lines.append(f"- Chain head: `{(fb.get('chain_head') or 'GENESIS')[:16]}...`")
else:
lines.append("- Forensic backend not configured")
- lines += [
- "",
- "---",
- "*OSS-tier report. PDF / Excel / branded reporting are not "
- "included in admina-framework.*",
- ]
return Response(
content="\n".join(lines) + "\n",
media_type="text/markdown; charset=utf-8",
diff --git a/admina/redteam/__init__.py b/admina/redteam/__init__.py
index f96ea98..267ca60 100644
--- a/admina/redteam/__init__.py
+++ b/admina/redteam/__init__.py
@@ -119,7 +119,7 @@ def _no_engine_reason(adapter: Any, engines: list[str], config: str | Path | Non
"""Why none of *engines* can run the corpora of *adapter*."""
if "rust" in engines:
if not detectors.rust_available():
- return "admina-core is not installed (install admina-framework[rust])"
+ return "admina-core is not installed (install admina[rust])"
keys = adapter.python_only_keys() if hasattr(adapter, "python_only_keys") else []
if keys:
names = ", ".join(f"agent_security.firewall.{key}" for key in keys)
diff --git a/core-rust/Cargo.lock b/core-rust/Cargo.lock
index 8d68a72..3ebecfe 100644
--- a/core-rust/Cargo.lock
+++ b/core-rust/Cargo.lock
@@ -4,7 +4,7 @@ version = 4
[[package]]
name = "admina_core"
-version = "0.13.2"
+version = "0.14.0"
dependencies = [
"chrono",
"hex",
diff --git a/core-rust/Cargo.toml b/core-rust/Cargo.toml
index e626d2f..17ec386 100644
--- a/core-rust/Cargo.toml
+++ b/core-rust/Cargo.toml
@@ -15,7 +15,7 @@
[package]
name = "admina_core"
-version = "0.13.2"
+version = "0.14.0"
edition = "2021"
description = "Admina governance engines — Rust core with Python bindings"
license = "Apache-2.0"
diff --git a/core-rust/README.md b/core-rust/README.md
index 4e82aa2..c1987ba 100644
--- a/core-rust/README.md
+++ b/core-rust/README.md
@@ -17,7 +17,7 @@ pip install admina-core
The Python framework auto-detects the Rust engine at runtime and falls
back to a pure-Python implementation if `admina-core` is not installed,
-so `admina-framework` always works on its own.
+so `admina` always works on its own.
## License
diff --git a/core-rust/pyproject.toml b/core-rust/pyproject.toml
index 43d2f1b..bd984ff 100644
--- a/core-rust/pyproject.toml
+++ b/core-rust/pyproject.toml
@@ -19,7 +19,7 @@ build-backend = "maturin"
[project]
name = "admina-core"
-version = "0.13.2"
+version = "0.14.0"
description = "Admina governance engines — Rust core with Python bindings (firewall, PII, loop breaker, hash chain)"
readme = "README.md"
requires-python = ">=3.11"
diff --git a/core-rust/uv.lock b/core-rust/uv.lock
index 82123dc..9a206d9 100644
--- a/core-rust/uv.lock
+++ b/core-rust/uv.lock
@@ -4,5 +4,5 @@ requires-python = ">=3.11"
[[package]]
name = "admina-core"
-version = "0.13.2"
+version = "0.14.0"
source = { editable = "." }
diff --git a/docs/guides/airgapped-deployment.md b/docs/guides/airgapped-deployment.md
index 0d39e06..c82dfcb 100644
--- a/docs/guides/airgapped-deployment.md
+++ b/docs/guides/airgapped-deployment.md
@@ -63,7 +63,7 @@ If you operate a private registry, `docker tag` + `docker push` to
### 2. Python wheels
-`pip install admina-framework[full]` resolves ~150 wheels from PyPI.
+`pip install admina[full]` resolves ~150 wheels from PyPI.
Pre-download them once on a connected host, then point pip at the
local directory.
@@ -71,13 +71,13 @@ local directory.
# On a host with Internet access:
mkdir -p admina-wheels
uv pip download \
- admina-framework[full] \
+ admina[full] \
--dest admina-wheels \
--python-version 3.11 \
--platform-extra manylinux2014_x86_64
# Transfer admina-wheels/ to the air-gapped host, then:
-uv pip install --no-index --find-links ./admina-wheels admina-framework[full]
+uv pip install --no-index --find-links ./admina-wheels admina[full]
```
For full reproducibility, pin the lock file: `uv lock --frozen`
diff --git a/docs/guides/package-name.md b/docs/guides/package-name.md
new file mode 100644
index 0000000..5ad5557
--- /dev/null
+++ b/docs/guides/package-name.md
@@ -0,0 +1,85 @@
+# The `admina` package name
+
+From **0.14.0**, Admina is published on PyPI as **`admina`**. The package
+`admina-framework`, which held the code up to 0.13.x, is no longer released
+after that. This is a breaking change for anything that installs
+`admina-framework`.
+
+What does not change: the Python module (`import admina`), the `admina`
+command, the extras, the Rust accelerator `admina-core` and the container
+images (`ghcr.io/admina-org/admina-proxy`, `ghcr.io/admina-org/admina-dashboard`).
+
+## Releases and package names
+
+| Releases | `admina-framework` | `admina` |
+|---|---|---|
+| up to 0.13.1 | the code | — |
+| 0.13.2 – 0.13.x | the code | an alias: no code, it installs `admina-framework` at the same version |
+| from 0.14.0 | 0.14.0 only: a final release that cannot be installed (see below) | the code |
+
+`admina-framework` 0.14.0 is a source distribution that stops the
+installation with this message, and leaves the installed packages as they
+are:
+
+```text
+admina-framework is now published as admina (since 0.14.0).
+Run: pip uninstall -y admina admina-framework && pip install admina
+Extras keep their names: admina-framework[proxy] is admina[proxy].
+See https://github.com/admina-org/admina/blob/main/docs/guides/package-name.md
+```
+
+So `pip install -U admina-framework`, or a requirement `admina-framework`
+without an upper bound, fails from 0.14.0 on. A pin such as
+`admina-framework==0.13.2` or `admina-framework<0.14` keeps installing the
+0.13 releases.
+
+## How to upgrade
+
+Both packages contain the `admina` module. Remove the installed ones first,
+then install `admina`:
+
+```bash
+pip uninstall -y admina admina-framework
+pip install "admina[proxy]" # the extras you used: same names
+```
+
+With uv:
+
+```bash
+uv pip uninstall admina admina-framework
+uv pip install "admina[proxy]"
+# in a uv project: uv remove admina-framework && uv add "admina[proxy]"
+```
+
+In `requirements.txt`, `pyproject.toml` or any other dependency list,
+replace `admina-framework` with `admina` and keep the extras and the
+version constraint:
+
+```diff
+- admina-framework[proxy,rust]>=0.13,<0.14
++ admina[proxy,rust]>=0.14,<0.15
+```
+
+A plugin created with `admina plugin create` depends on `admina-framework`
+in its `pyproject.toml`: change that line in the same way.
+
+Check the result:
+
+```bash
+python -c "import admina; print(admina.__version__)" # 0.14.0 or later
+pip list | grep -i admina # admina (and admina-core with [rust])
+```
+
+## If `import admina` fails after the upgrade
+
+Installing `admina` 0.14 while `admina-framework` 0.13 is installed, and
+then uninstalling `admina-framework`, removes the files of the `admina`
+module: pip and uv delete every file that the uninstalled package had
+installed, and both packages installed the same files. `pip list` still
+shows `admina`, but `import admina` raises `ModuleNotFoundError`. Reinstall
+it:
+
+```bash
+pip install --force-reinstall "admina[proxy]"
+# or: uv pip install --reinstall "admina[proxy]"
+```
diff --git a/docs/index.md b/docs/index.md
index 76be9f1..75bfcd2 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -32,13 +32,14 @@ audited, EU AI Act compliance tracked. Works in-process (SDK) and over the netwo
## Install
```bash
-pip install "admina-framework[proxy]" # Recommended: SDK + proxy + dashboard
-pip install "admina-framework[full]" # + NLP (spaCy) + telemetry (OTEL)
-pip install admina-framework # SDK only — embed it in another service
+pip install "admina[proxy]" # Recommended: SDK + proxy + dashboard
+pip install "admina[full]" # + NLP (spaCy) + telemetry (OTEL)
+pip install admina # SDK only — embed it in another service
```
-> Distribution name `admina-framework`, import name `admina`
-> (same pattern as `python-dateutil` → `import dateutil`).
+> Distribution name and import name: `admina` (up to 0.13.x the
+> distribution was `admina-framework`; see the
+> [package name guide](guides/package-name.md)).
## 30-second example
diff --git a/mkdocs.yml b/mkdocs.yml
index 3cd95a9..fe096ff 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -51,6 +51,7 @@ nav:
- Integrations: guides/integrations.md
- Air-gapped deployment: guides/airgapped-deployment.md
- Upgrading to 0.13: guides/upgrade-0.13.md
+ - The admina package name: guides/package-name.md
- SDK Reference:
- Overview: api/sdk.md
- GovernedModel: api/governed-model.md
diff --git a/packaging/admina-framework/README.md b/packaging/admina-framework/README.md
new file mode 100644
index 0000000..6b5e68c
--- /dev/null
+++ b/packaging/admina-framework/README.md
@@ -0,0 +1,16 @@
+# admina-framework
+
+Admina is published as [`admina`](https://pypi.org/project/admina/) since
+0.14.0. This last release of `admina-framework` cannot be installed: it
+stops with the commands to switch.
+
+```bash
+pip uninstall -y admina admina-framework
+pip install admina # extras keep their names: "admina[proxy]"
+```
+
+The module (`import admina`), the `admina` command and the extras did not
+change. Releases up to 0.13.x of `admina-framework` remain installable with a
+pin such as `admina-framework<0.14`.
+
+Upgrade guide: https://github.com/admina-org/admina/blob/main/docs/guides/package-name.md
diff --git a/packaging/admina-framework/setup.py b/packaging/admina-framework/setup.py
new file mode 100644
index 0000000..369ed0b
--- /dev/null
+++ b/packaging/admina-framework/setup.py
@@ -0,0 +1,23 @@
+# Copyright © 2025–2026 Stefano Noferi & Admina contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+
+# The last release of admina-framework: the code is published as admina
+# since 0.14.0. Installing this source distribution stops with the commands
+# to switch, before pip or uv change the installed packages.
+
+raise SystemExit(
+ "\n\nadmina-framework is now published as admina (since 0.14.0).\n"
+ "Run: pip uninstall -y admina admina-framework && pip install admina\n"
+ "Extras keep their names: admina-framework[proxy] is admina[proxy].\n"
+ "See https://github.com/admina-org/admina/blob/main/docs/guides/package-name.md\n"
+)
diff --git a/packaging/admina/README.md b/packaging/admina/README.md
deleted file mode 100644
index 9b8fed1..0000000
--- a/packaging/admina/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# admina
-
-`pip install admina` installs [`admina-framework`](https://pypi.org/project/admina-framework/),
-the Admina governed AI development framework, at the same version. This
-package has no code of its own; `import admina` comes from `admina-framework`.
-
-Every extra of `admina-framework` is available under the same name:
-
-```bash
-pip install admina # SDK
-pip install "admina[proxy]" # SDK + proxy + dashboard
-pip install "admina[full]" # proxy + NLP + telemetry
-```
-
-Documentation, changelog and source: https://github.com/admina-org/admina
diff --git a/packaging/admina/pyproject.toml b/packaging/admina/pyproject.toml
deleted file mode 100644
index 5c8544c..0000000
--- a/packaging/admina/pyproject.toml
+++ /dev/null
@@ -1,69 +0,0 @@
-
-# Copyright © 2025–2026 Stefano Noferi & Admina contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# The PyPI project "admina": no code of its own, it installs admina-framework
-# at the same version. Every extra of admina-framework has an extra of the same
-# name here (admina[proxy] installs admina-framework[proxy]). The version and
-# the pin are checked by scripts/check-versions.py, the extras by
-# tests/test_admina_alias.py; release.yml publishes it after admina-framework.
-
-[build-system]
-requires = ["setuptools>=68.0"]
-build-backend = "setuptools.build_meta"
-
-[project]
-name = "admina"
-version = "0.13.2"
-description = "Admina — governed AI development framework (installs admina-framework)"
-readme = "README.md"
-requires-python = ">=3.11"
-license = "Apache-2.0"
-authors = [
- {name = "Stefano Noferi", email = "info@admina.org"},
-]
-maintainers = [
- {name = "Stefano Noferi", email = "info@admina.org"},
-]
-classifiers = [
- "Development Status :: 4 - Beta",
- "Programming Language :: Python :: 3",
-]
-dependencies = ["admina-framework==0.13.2"]
-
-[project.urls]
-Homepage = "https://admina.org"
-Repository = "https://github.com/admina-org/admina"
-Documentation = "https://github.com/admina-org/admina#readme"
-Changelog = "https://github.com/admina-org/admina/blob/main/CHANGELOG.md"
-
-[project.optional-dependencies]
-proxy = ["admina-framework[proxy]==0.13.2"]
-proxy-minimal = ["admina-framework[proxy-minimal]==0.13.2"]
-nlp = ["admina-framework[nlp]==0.13.2"]
-telemetry = ["admina-framework[telemetry]==0.13.2"]
-rust = ["admina-framework[rust]==0.13.2"]
-full = ["admina-framework[full]==0.13.2"]
-openai = ["admina-framework[openai]==0.13.2"]
-ollama = ["admina-framework[ollama]==0.13.2"]
-anthropic = ["admina-framework[anthropic]==0.13.2"]
-mistral = ["admina-framework[mistral]==0.13.2"]
-gemini = ["admina-framework[gemini]==0.13.2"]
-bedrock = ["admina-framework[bedrock]==0.13.2"]
-adapters = ["admina-framework[adapters]==0.13.2"]
-presidio = ["admina-framework[presidio]==0.13.2"]
-all = ["admina-framework[all]==0.13.2"]
-
-[tool.setuptools]
-packages = []
diff --git a/pyproject.toml b/pyproject.toml
index 0c5ae60..d6d8864 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -18,8 +18,8 @@ requires = ["setuptools>=68.0"]
build-backend = "setuptools.build_meta"
[project]
-name = "admina-framework"
-version = "0.13.2"
+name = "admina"
+version = "0.14.0"
description = "Admina — governed AI development framework"
readme = "README.md"
requires-python = ">=3.11"
@@ -101,7 +101,7 @@ nlp = [
# NOTE: the `en_core_web_sm` model is NOT declared as a direct
# dependency here because PyPI rejects wheels with URL-pinned
# dependencies (PEP 440 "direct references"). After installing
- # `admina-framework[nlp]`, run:
+ # `admina[nlp]`, run:
# python -m spacy download en_core_web_sm
# The PIIRedactor logs a clear error if the model is missing.
]
@@ -126,14 +126,14 @@ rust = [
# stops). It is opt-in so the default install keeps the broader Python
# detection coverage; enable [rust] when latency matters more.
#
- # admina-core and admina-framework are released in lockstep from the same
+ # admina-core and admina are released in lockstep from the same
# tag (scripts/check-versions.py enforces manifest alignment). The
# published metadata carries the version range below; uv.lock resolves
# admina-core from ./core-rust instead ([tool.uv.sources]), so
# `uv sync --extra rust` (or --all-extras) builds the engine of the same
# checkout, which needs a Rust toolchain. The range takes the 0.13.x
# releases of admina-core, the line released with this framework.
- "admina-core>=0.13.0,<0.14",
+ "admina-core>=0.14.0,<0.15",
]
# NOTE: the [guardrailsai] extra was removed in v0.9.0 because the
# upstream `guardrails-ai` package is currently in PyPI quarantine
@@ -141,7 +141,7 @@ rust = [
# admina/plugins/builtin/guards/guardrailsai_guard.py is preserved; if
# you have a local copy of guardrails-ai installed, the plugin will
# detect it and work. Re-introduce the extra once upstream is restored.
-full = ["admina-framework[proxy,nlp,telemetry]"]
+full = ["admina[proxy,nlp,telemetry]"]
# Model-adapter provider SDKs — each adapter lazy-imports its SDK, so the
# extra only controls whether the provider wheel is present.
openai = ["openai>=1.0,<4"]
@@ -150,7 +150,7 @@ anthropic = ["anthropic>=0.39,<2"]
mistral = ["mistralai>=1.0,<4"]
gemini = ["google-genai>=1.0,<3"]
bedrock = ["boto3>=1.34,<2"]
-adapters = ["admina-framework[openai,ollama,anthropic,mistral,gemini,bedrock]"]
+adapters = ["admina[openai,ollama,anthropic,mistral,gemini,bedrock]"]
# Microsoft Presidio as a selectable PII engine. Presidio does detection only;
# Admina keeps its own masking, so the output format matches the default
# spaCy+regex engine. ADMINA_PRESIDIO_NLP_MODELS sets the spaCy pipeline of each
@@ -159,7 +159,7 @@ adapters = ["admina-framework[openai,ollama,anthropic,mistral,gemini,bedrock]"]
# installed separately, like [nlp]:
# python -m spacy download en_core_web_sm
presidio = ["presidio-analyzer>=2.2,<3"]
-all = ["admina-framework[proxy,nlp,telemetry,adapters,presidio]"]
+all = ["admina[proxy,nlp,telemetry,adapters,presidio]"]
[dependency-groups]
dev = [
diff --git a/scripts/build-admina-framework-sdist.py b/scripts/build-admina-framework-sdist.py
new file mode 100755
index 0000000..db0c717
--- /dev/null
+++ b/scripts/build-admina-framework-sdist.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python3
+
+# Copyright © 2025–2026 Stefano Noferi & Admina contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Build the last admina-framework release: a source distribution that
+stops its installation with the commands to switch to ``admina``.
+
+Usage (from the repository root)::
+
+ python scripts/build-admina-framework-sdist.py dist-framework/
+
+The version is the one of ``pyproject.toml``. The archive holds
+``PKG-INFO`` (with ``packaging/admina-framework/README.md`` as the
+description), a ``pyproject.toml`` that names the setuptools backend, and
+``packaging/admina-framework/setup.py``, which raises ``SystemExit`` with the
+message: pip and uv run it before they change the installed packages.
+"""
+
+from __future__ import annotations
+
+import io
+import sys
+import tarfile
+import tomllib
+from pathlib import Path
+
+REPO = Path(__file__).resolve().parent.parent
+
+_PYPROJECT = """[build-system]
+requires = ["setuptools>=68.0"]
+build-backend = "setuptools.build_meta"
+"""
+
+
+def pkg_info(version: str, description: str) -> str:
+ """The core metadata of the release."""
+ return (
+ "Metadata-Version: 2.4\n"
+ "Name: admina-framework\n"
+ f"Version: {version}\n"
+ "Summary: Admina is published as admina: this release cannot be installed\n"
+ "Project-URL: Homepage, https://pypi.org/project/admina/\n"
+ "Project-URL: Repository, https://github.com/admina-org/admina\n"
+ "License-Expression: Apache-2.0\n"
+ "Requires-Python: >=3.11\n"
+ "Description-Content-Type: text/markdown\n"
+ "\n"
+ f"{description}"
+ )
+
+
+def build(out_dir: Path, repo: Path = REPO) -> Path:
+ """Write ``admina_framework-