Async-native Python web framework with flow-first routing
Project description
Aquilia is an async-native, manifest-first Python web framework that auto-discovers modules, wires dependency injection, and generates infrastructure manifests — no routing glue code, no manual Dockerfiles.
Features
- Manifest-First Architecture — Modules declare controllers, services, and middleware in
manifest.py. Aquilia discovers and wires them automatically. - Auto-Discovery —
PackageScannertraverses your workspace, finds modules, and registers them without boilerplate. - Scoped Dependency Injection — Hierarchical DI (
singleton,app,requestscopes) with annotation-driven providers. - Structured Fault System — Every error is a typed
Faultsubclass with domain, severity, code, and recovery strategy. No raw exceptions. - Clearance System — Declarative, multi-dimensional access control with access levels, entitlements, conditions, and tenant compartments.
- API Versioning with Sunset — Epoch-based versioning with channel promotion, multi-strategy resolution (URL, header, query, media type), and RFC 8594 sunset enforcement.
- SSE Streaming — First-class Server-Sent Events with
SSEResponseandSSEEventfor real-time data and LLM token streaming. - OpenTelemetry — Built-in distributed tracing via
OTelConfigand ASGI instrumentation middleware. - Production Security — HMAC-verified caches, path traversal protection, CSRF/CORS/CSP/HSTS guards, sandboxed Jinja2 templates.
Installation
pip install aquilia
jinja2 (templates) and aiosqlite (SQLite) are bundled in core — no extras needed to get started.
| Extra | What it adds |
|---|---|
aquilia |
Core framework — controllers, DI, ORM, templates, filesystem, SQLite |
aquilia[auth] |
Argon2 hashing, JWT, OAuth, cryptography |
aquilia[postgres] |
asyncpg driver for PostgreSQL |
aquilia[redis] |
Redis cache & WebSocket backends |
aquilia[otel] |
OpenTelemetry API, SDK, OTLP exporter, ASGI instrumentation |
aquilia[mail] |
SMTP email provider |
aquilia[server] |
Gunicorn + Uvicorn workers for production |
aquilia[full] |
Everything above — auth, postgres, redis, otel, mail, server, multipart |
Quick Start
Aquilia is workspace-first — scaffold projects through the aq CLI.
1 — Create a workspace
aq init workspace my-app
cd my-app
This generates workspace.py, config/, and a starter page serving GET / immediately.
2 — Add a module
aq add module users
Generates modules/users/ with manifest.py, controllers.py, services.py, and models.py.
3 — Write a controller
# modules/users/controllers.py
from aquilia import Controller, GET, POST, RequestCtx, Response
from aquilia.controller.validation import validate_body
class UsersController(Controller):
prefix = "/users"
tags = ["users"]
@GET("/")
async def list_users(self, ctx: RequestCtx):
return Response.json({"users": []})
@POST("/")
@validate_body(CreateUserBlueprint)
async def create_user(self, ctx: RequestCtx, body: dict):
return Response.json({"created": body}, status=201)
No manual route registration — controllers in a module's manifest.py are discovered and wired automatically.
4 — Run the development server
aq serve
Serves on http://127.0.0.1:8000 with hot reload.
CLI
| Command | Description |
|---|---|
aq init workspace <name> |
Scaffold a new workspace |
aq add module <name> |
Add a module with manifest, controller, services, models |
aq serve |
Start development server with hot reload |
aq compile |
Compile manifests into a frozen artifact |
aq validate |
Validate manifests, routes, and DI graph |
aq inspect |
Inspect compiled routes, DI providers, and version graph |
Code Examples
Structured Faults
from aquilia.faults import Fault, FaultDomain, Severity
class PaymentRequiredFault(Fault):
def __init__(self, plan: str):
super().__init__(
code="PAYMENT_REQUIRED",
message=f"Upgrade to {plan} to access this feature",
domain=FaultDomain.SECURITY,
severity=Severity.WARN,
retryable=False,
public=True,
)
raise PaymentRequiredFault(plan="pro")
Or use built-in HTTP faults:
from aquilia.faults import NotFoundFault, ForbiddenFault
raise NotFoundFault(detail="/api/users/999 does not exist")
raise ForbiddenFault(detail="Insufficient permissions")
Clearance System — Declarative Access Control
from aquilia import Controller, GET, POST, DELETE, RequestCtx
from aquilia.auth.clearance import Clearance, AccessLevel, grant, exempt, is_verified, is_owner_or_admin
class DocumentController(Controller):
prefix = "/documents"
clearance = Clearance(level=AccessLevel.AUTHENTICATED)
@GET("/")
@grant(level=AccessLevel.PUBLIC)
async def list_public(self, ctx: RequestCtx):
return {"docs": []}
@POST("/")
@grant(entitlements=["documents:write"], conditions=[is_verified])
async def create(self, ctx: RequestCtx):
...
@DELETE("/{doc_id}")
@grant(level=AccessLevel.CONFIDENTIAL, conditions=[is_owner_or_admin])
async def delete(self, ctx: RequestCtx, doc_id: str):
...
SSE Streaming
import asyncio
from aquilia import Controller, GET, RequestCtx
from aquilia.sse import SSEEvent, SSEResponse
class StreamController(Controller):
prefix = "/stream"
@GET("/events")
async def live_events(self, ctx: RequestCtx):
return SSEResponse(self._generate())
async def _generate(self):
for i in range(100):
yield SSEEvent(data=f"event {i}", event="update", id=str(i))
await asyncio.sleep(0.5)
API Versioning with Sunset
from aquilia import Controller, GET
from aquilia.versioning import version, SunsetPolicy, VERSION_NEUTRAL
class UsersV2Controller(Controller):
prefix = "/users"
version = "2.0"
@GET("/")
async def list_v2(self, ctx):
...
class UsersV1Controller(Controller):
prefix = "/users"
version = "1.0"
sunset = SunsetPolicy(grace_period="180d", warn_header=True)
@GET("/")
async def list_v1(self, ctx):
...
Architecture
The boot sequence: Manifests → Aquilary → RuntimeRegistry → Controllers → ASGI
| Subsystem | Purpose |
|---|---|
| Aquilary | Core manifest registry, metadata, runtime wiring |
| Controller | Route decorators (@GET, @POST), OpenAPI generation, filtering, pagination |
| DI | Hierarchical dependency injection with singleton/app/request scopes |
| Faults | Structured error system with 14+ domains, typed HTTP faults |
| Auth | JWT/session auth, MFA, OAuth, RBAC/ABAC, clearance guards |
| Flow | Typed routing and composable request pipelines with effect scopes |
| Models/ORM | Async ORM with query builder, migrations, transactions |
| Templates | Sandboxed Jinja2 with bytecode caching and HMAC integrity |
| Cache | Multi-backend caching with decorators and middleware |
| Storage | Async file storage (local, S3, GCS, Azure, SFTP, memory) |
| Tasks | Background job system with priority queues and scheduling |
| Multi-provider email (SMTP, SES, SendGrid) | |
| SSE | Server-Sent Events streaming (SSEResponse, SSEEvent) |
| WebSockets | Socket controllers with event/subscription/guard decorators |
| Versioning | Epoch-based API versioning with sunset lifecycle |
| OTel | OpenTelemetry distributed tracing middleware and configuration |
| Admin | Auto-detecting admin dashboard with audit logging |
Testing
python -m pytest tests/ -v
python -m pytest tests/ --cov=aquilia --cov-report=html
Learn More
- Documentation: https://aquilia.tubox.cloud
- Architecture Guide: https://aquilia.tubox.cloud/docs/architecture
- Quick Start: https://aquilia.tubox.cloud/docs/quickstart
- Changelog: CHANGELOG.md
- Security: SECURITY.md
- Contributing: CONTRIBUTING.md
Built with ❤️ by the Aquilia Team
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aquilia-1.1.1.tar.gz.
File metadata
- Download URL: aquilia-1.1.1.tar.gz
- Upload date:
- Size: 1.8 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d53e9811b8a53c8a20204a0c5212cd325386b93ad962926606f4c5589638296
|
|
| MD5 |
56039a0946b50e7358df15c23581de81
|
|
| BLAKE2b-256 |
5f2d29d28d3efdc207a6c2b29c81d74d2b9a6a5ac7364c9688d4552226857169
|
Provenance
The following attestation bundles were made for aquilia-1.1.1.tar.gz:
Publisher:
release.yml on tubox-labs/Aquilia
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aquilia-1.1.1.tar.gz -
Subject digest:
3d53e9811b8a53c8a20204a0c5212cd325386b93ad962926606f4c5589638296 - Sigstore transparency entry: 1758679346
- Sigstore integration time:
-
Permalink:
tubox-labs/Aquilia@145d3f2c65c5784953fea679514134438aad7041 -
Branch / Tag:
refs/tags/v1.1.1 - Owner: https://github.com/tubox-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@145d3f2c65c5784953fea679514134438aad7041 -
Trigger Event:
push
-
Statement type:
File details
Details for the file aquilia-1.1.1-py3-none-any.whl.
File metadata
- Download URL: aquilia-1.1.1-py3-none-any.whl
- Upload date:
- Size: 2.1 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cde804ed00a8d56dd3acfecfe1ae4b22794c99d3d0dec20b36decf18359014e2
|
|
| MD5 |
bb2eef80de3db0a9bf5c4f1162b47476
|
|
| BLAKE2b-256 |
ebe6dbcdeebaccfb74630764c084e2b6221a61dae2ffc76bfe7d36d730ebc2f2
|
Provenance
The following attestation bundles were made for aquilia-1.1.1-py3-none-any.whl:
Publisher:
release.yml on tubox-labs/Aquilia
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aquilia-1.1.1-py3-none-any.whl -
Subject digest:
cde804ed00a8d56dd3acfecfe1ae4b22794c99d3d0dec20b36decf18359014e2 - Sigstore transparency entry: 1758679391
- Sigstore integration time:
-
Permalink:
tubox-labs/Aquilia@145d3f2c65c5784953fea679514134438aad7041 -
Branch / Tag:
refs/tags/v1.1.1 - Owner: https://github.com/tubox-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@145d3f2c65c5784953fea679514134438aad7041 -
Trigger Event:
push
-
Statement type: