This release is a pre-release and may not be stable for production use.
An architectural chassis for building modular applications on top of FastAPI.
Structuring transactional boundaries, constructor dependency injection, and field-level access controls while preserving native FastAPI semantics.
🧭 Overview
FastAPI provides an efficient, ergonomic foundation for HTTP handling, asynchronous I/O, and data validation using Pydantic. However, as codebases grow beyond simple APIs into larger services or modular monoliths, engineering teams frequently face common structural challenges:
- Session Lifetime & Leaks: Database sessions can inadvertently leak across concurrent coroutines or terminate prematurely during background tasks.
- Transaction Coordination: Workflows that update multiple repositories often lack a unified, atomic transaction boundary, risking partial writes when a middle step fails.
- Schema Proliferation: Writing and maintaining separate Pydantic models (
UserPublic,UserInternal,UserAdminResponse) solely to conceal specific fields across user roles introduces repetitive boilerplate. - Module Coupling: Large domain modules frequently develop tangled dependency graphs and circular imports when interacting with shared databases.
Full-stack monolithic frameworks solve these issues by introducing comprehensive conventions, coupled ORMs, and centralized registries. While effective, this approach can reduce architectural flexibility.
ZCore is designed as an intermediate layer. It does not hide FastAPI or replace its router. Instead, it provides a set of decoupled architectural primitives—such as a re-entrant Unit of Work, constructor-based Inversion of Control (IoC), context-aware schema filtering (Zchema), and lifecycle plugins—built on top of standard FastAPI, SQLAlchemy 2.0 (Async), and Pydantic V2.
You can adopt individual components where they solve concrete architectural needs or use the structured chassis as a cohesive pattern for modular application design.
🛍️ Reference Implementation: ZShop
To examine how these architectural patterns interact in an end-to-end codebase, refer to ZShop, a modular monolith reference application:
- Context & Security Inspection: Demonstrates active correlation IDs (
x-request-id), execution profiling, and role-based data projection. - Role-Based Schema Pruning: Displays how confidential attributes (such as supplier costs) are dynamically excluded based on the authenticated context via
Zchema. - Atomic Rollback Demonstration: Validates multi-repository rollback guarantees by simulating invariant violations during order checkout.
- Contract-Driven Decoupling: Demonstrates cross-domain communication via Python
Protocols(ProductContract) rather than direct database model imports.
👉 Explore the ZShop Reference Codebase
⚖️ Architectural Comparison
| Area | Plain FastAPI | Heavy Monoliths (e.g., Django) | FastAPI with ZCore |
|---|---|---|---|
| Philosophy | Minimalist microframework; architectural organization is left entirely to the developer. | Batteries-included, opinionated; coupled to built-in ORM and global application registries. | Composable layer; provides structured architectural patterns while keeping routers and schemas standard. |
| Field-Level Security | Manual if/else checks or maintaining distinct Pydantic DTOs for each access level. |
Model-level field permissions or specialized serializer layers. | Context-aware pruning (Zchema); dynamically filters restricted fields across validation, serialization, and dynamic schema introspection. |
| Transaction Management | Manual session.commit() calls across routes and services; potential for partial writes. |
Built-in transaction blocks (transaction.atomic()). |
Re-entrant UnitOfWork; depth-aware coordination with domain events buffered until root commit succeeds. |
| Background Processing | Request-scoped sessions passed to BackgroundTasks often encounter closed session errors. |
Relies on external task queue workers (e.g., Celery) even for simple background steps. | Scoped @background_task; isolates session allocation and IoC lifecycles from completed request scopes. |
| Modular Domain Design | Standard APIRouter instances; vulnerable to circular imports as features expand. |
Strict app layout and global settings configuration. | DAG-driven Plugin system; topological startup sorting and pure Python Protocol contracts for interface decoupling. |
| Dataset Pagination | Manual offset / limit SQL slicing, which may suffer performance degradation on large tables. |
Built-in offset paginators. | Keyset Cursor Pagination; compound keyset traversal with URL-safe base64 cursors, alongside dynamic JSON filtering. |
| Test Isolation | Manual database cleanup or recreating schema fixtures between test runs. | Transactional test cases rolling back writes per test method. | Rollback harness via ZTestClient; automated savepoint rollbacks, container isolation, and context mocking. |
🚀 Quick Start
1. Installation
pip install "fastapi-zcore-framework[all]"
2. Initialize a Project
The interactive zc CLI configures your workspace, sets up a virtual environment (uv or pip), and bootstraps the appropriate asynchronous database driver:
# Interactive setup
zc init core_api && cd core_api
# Scaffold a domain module
zc startapp tasks
3. Define Your Domain Model
In tasks/models.py (standard SQLAlchemy 2.0):
import uuid
from sqlalchemy.orm import Mapped, mapped_column
from zcore import Base, SoftDeleteMixin
class Task(Base, SoftDeleteMixin):
__tablename__ = "tasks"
id: Mapped[uuid.UUID] = mapped_column(primary_key=True, default=uuid.uuid4)
title: Mapped[str] = mapped_column(index=True)
is_completed: Mapped[bool] = mapped_column(default=False)
4. Run the Development Server
zc run
The application starts at http://127.0.0.1:8000 with 8 standard endpoints managed by BaseRouter:
POST /tasks/— Entity creationGET /tasks/{id}— Single-record retrieval with primary key inspectionGET /tasks/— List retrieval supporting offset or keyset cursor paginationPOST /tasks/search— Dynamic nested JSON filtering and sortingPOST /tasks/lookup— Lightweight, column-projected endpoint for relational referencesPUT /tasks/{id}&PATCH /tasks/{id}— Complete and partial updatesDELETE /tasks/{id}— Soft delete (or physical purge via?force=true)GET /tasks/_schema— Role-aware schema introspection (all actions or filtered via?action=create|update|view|lookup)
🏛️ Core Architectural Components
1. Context Shielding & Field-Level Access Control (Zchema)
Problem
Managing multiple versions of the same schema (ProductCustomerView, ProductInternalView, ProductAdminUpdate) to hide sensitive attributes (such as purchase cost or internal remarks) introduces redundancy and increases the risk of accidental data leaks.
Solution
Define the schema once by inheriting from Zchema. When fields are marked as restricted within the current request context (ctx.restricted_fields), ZCore prunes them across:
- Input validation: Silently discards restricted fields to prevent mass assignment.
- Output serialization: Removes restricted attributes before JSON encoding.
- Schema introspection: Omits restricted properties dynamically when querying the
/_schemaendpoint.
import uuid
from decimal import Decimal
from zcore import Zchema
class ProductResponse(Zchema):
__model__ = "products"
id: uuid.UUID
name: str
price: Decimal
cost_price: Decimal | None = None # Internal margin
supplier_notes: str | None = None # Vendor agreement notes
When restricted fields are pruned from a response, ZCore appends a Vary: Authorization, Cookie header to prevent shared HTTP caches or CDNs from caching privileged data representations for unprivileged clients.
2. Atomic Unit of Work & Deferred Domain Events (UnitOfWork)
Problem
When business operations touch multiple repositories, issuing separate commits introduces the risk of partial database writes if an intermediate step fails. Additionally, publishing domain events (or sending notifications) before a database transaction physically commits can lead to state inconsistency if the transaction ultimately rolls back.
Solution
ZCore implements a depth-aware, re-entrant UnitOfWork. Nested scopes flush changes safely without premature commits, while domain events remain buffered and are dispatched only after the root commit succeeds:
from zcore import UnitOfWork
async with UnitOfWork(session=self.session, dispatcher=self.dispatcher) as uow:
# 1. Update inventory
await self.inventory_service.adjust_stock(product_id, -quantity)
# 2. Persist order entity
self.order_repo.add(new_order)
await self.session.flush()
# 3. Buffer domain event
# If any error occurs before commit completes, this event is discarded.
uow.register_event("order.created", {"order_id": str(new_order.id)})
3. Constructor-Based Dependency Injection (IoC Container)
Problem
In complex applications, deep chains of FastAPI Depends(...) can become verbose. Furthermore, domain modules risk circular imports when cross-referencing concrete repository implementations.
Solution
The built-in IoC container supports constructor-based auto-wiring via type annotations, caching constructor signatures to minimize reflection overhead. It supports Singleton, Scoped, and Transient lifecycles, and automatically skips parameters with default values unless explicitly registered:
# Pure Python contract (contracts/catalog.py)
from typing import Protocol, runtime_checkable
@runtime_checkable
class ProductContract(Protocol):
async def adjust_stock(self, product_id: str, delta: int) -> None: ...
# Domain implementation (apps/orders/services.py)
from contracts.catalog import ProductContract
class OrderService(BaseService[Orders]):
# Dependencies are resolved by constructor type hints
def __init__(self, repository: OrderRepository, inventory: ProductContract):
super().__init__(model=Orders, repository=repository)
self.inventory = inventory
4. Isolated Background Execution (@background_task)
Problem
FastAPI executes background tasks after completing the HTTP response. If a task receives an AsyncSession bound to the finished request lifecycle, the session is often closed by the time execution begins, causing connection errors.
Solution
The @background_task decorator creates an independent execution scope. It provisions a dedicated database session, isolates context variables, and auto-wires type-annotated dependencies directly from the container:
import uuid
from zcore import background_task
@background_task
async def generate_invoice_task(
order_id: uuid.UUID,
order_repo: OrderRepository, # Injected with an independent session
) -> None:
order = await order_repo.get(id=order_id)
# Operates safely outside of the HTTP request lifecycle
5. Composite Primary Keys & Keyset Pagination
Capabilities
- Composite Primary Keys:
BaseRepositorynatively handles composite models and PostgreSQL partitioned tables (e.g.,(id, operation_date)). Operations use tuple-based lookups (tuple_(*pks).in_(...)), allowing PostgreSQL to perform partition pruning without full table scans. - Compound Keyset Pagination:
CursorPaginationsupports non-primary-key sorting columns using compound keyset conditions(col < val) OR (col == val AND pk < last_pk). It handles type coercion fordate,datetime,UUID, and numeric types. - Mutual Exclusivity:
SearchRequestvalidates against conflicting pagination modes, raising a 422 error if both offset (page > 1) and keyset (cursor) parameters are supplied simultaneously.
6. Isolated Testing Harness (ZTestClient)
Problem
Integration tests that write directly to a database typically require slow schema teardowns or manual cleanup scripts to prevent test state leakage.
Solution
ZTestClient coordinates tests within transactional savepoints. Database modifications are automatically rolled back upon test completion, while container bindings and event listeners are restored from snapshots:
import pytest
from zcore.testing import ZTestClient
from main import app
@pytest.mark.asyncio
async def test_order_placement_atomicity():
async with ZTestClient(
app,
user_id="test-user-id",
scopes=["orders:create", "products:view"]
) as client:
response = await client.post("/checkout/orders/", json={...})
assert response.status_code == 201
# Transaction changes are rolled back automatically upon context exit
🛠️ Developer Tooling (zc CLI)
ZCore provides an interactive command-line interface powered by Questionary and Rich:
$ zc
⚡ ZCore Framework v0.1.0-rc.3 • Modern Modular Monolith
FastAPI • SQLAlchemy 2.0 • Pydantic V2
? What framework task would you like to perform?
❯ 🧩 startapp — Scaffold a modular domain app / plugin
⚡ run — Launch Uvicorn development server
📋 genenv — Generate template .env from Settings class
🔑 gensecret — Generate cryptographically secure SECRET_KEY
📦 init — Scaffold a new ZCore project
🚪 exit — Exit CLI
Command Reference
| Command | Key Options | Purpose |
|---|---|---|
zc |
— | Launches interactive dashboard |
zc init [name] |
--db [sqlite|postgres|mysql], -y |
Scaffolds project files, .env, and initializes virtual environment |
zc startapp [name] |
--template / --no-template, --test, -y |
Generates architectural layers (models, schemas, repos, services, routers) |
zc run [app] |
--host, --port, --reload, --workers, --env-file |
Starts Uvicorn with hierarchical configuration (CLI > .env > Defaults) |
zc gensecret |
— | Generates a 64-character cryptographic SECRET_KEY |
zc genenv |
-o <output>, -f / --force |
Introspects active Pydantic Settings and outputs a template .env |
📢 Testing & Community Validation (Release Candidate rc.3)
We are currently evaluating v0.1.0-rc.3 across real-world workloads prior to finalizing the v1.0.0 stable release.
ZCore was created to address architectural friction points encountered in production environments. We welcome technical feedback, bug reports, and discussion on edge cases:
- Evaluate the Showcase: Review ZShop to observe how components interact in a concrete project.
- Test Architectural Boundaries: Evaluate
UnitOfWorkbehavior under nested operations, verify complex queries withSearchEngine, or test composite key models. - Report Issues: If an abstraction feels rigid, if a type hint fails strict static analysis, or if an edge case is unhandled, please open a detailed issue on GitHub.
👉 Submit Issues & Technical Feedback on GitHub
📚 Documentation
Detailed guides, design explanations, and API references are available at our documentation portal:
- Quick Start Tutorial — Basic project initialization and endpoint setup.
- Layer-by-Layer Guide — Walkthrough of model, repository, service, and router separation.
- Architectural Comparisons — Technical comparisons with plain FastAPI and Django.
- How-To Guides — Practical patterns for Keyset Pagination, File Storage, and Caching.
- Core Concepts — Deep dives into DI auto-wiring, Unit of Work, Kernel DAG, and Context shielding.
- API Reference — Method signatures and parameter details.
📄 License
ZCore Framework is open-source software licensed under the Apache License 2.0.
See the LICENSE file for details.
Maintained by Ali Alf Ostovar and the Baseryn open-source community.
Metadata
Release files for fastapi-zcore-framework 0.1.0rc3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| fastapi_zcore_framework-0.1.0rc3.tar.gz | 160.1 kB | With provenance | Details for fastapi_zcore_framework-0.1.0rc3.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| fastapi_zcore_framework-0.1.0rc3-py3-none-any.whl | Python 3 | none | any | Details for fastapi_zcore_framework-0.1.0rc3-py3-none-any.whl |
Total release size: 280.8 kB
Release files / fastapi_zcore_framework-0.1.0rc3.tar.gz
| Download URL | fastapi_zcore_framework-0.1.0rc3.tar.gz |
|---|---|
| Size | 160.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8974aa48b9e0d8b4d9eef49d2d4091c9c71cc31451f69edf8c39c32c7f699b97
|
|
BLAKE2b-256 checksum How to use checksums |
9b77a93a734ecd220f7e7501839494419b16772d693cc5c5723cac18bdeb1b46
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logRelease files / fastapi_zcore_framework-0.1.0rc3-py3-none-any.whl
| Download URL | fastapi_zcore_framework-0.1.0rc3-py3-none-any.whl |
|---|---|
| Size | 120.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
44f18bb0911150a172c2c2e5f1a8c158b8e99ffa8c6168fecf13de00bca07370
|
|
BLAKE2b-256 checksum How to use checksums |
f363e3a2563c8aa5ee6e569fa9e384334a8de321fb14fb90c061319e983fcaca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logSecurity for fastapi-zcore-framework 0.1.0rc3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for fastapi_zcore_framework-0.1.0rc3.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.