ferrox-py 1.0.0__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.
- ferrox_py-1.0.0/.github/workflows/ci.yml +34 -0
- ferrox_py-1.0.0/.gitignore +5 -0
- ferrox_py-1.0.0/.gitlab-ci.yml +27 -0
- ferrox_py-1.0.0/.gitmodules +3 -0
- ferrox_py-1.0.0/Dockerfile +14 -0
- ferrox_py-1.0.0/PKG-INFO +95 -0
- ferrox_py-1.0.0/README.md +68 -0
- ferrox_py-1.0.0/docs/abstractions/pipes-interceptors.md +38 -0
- ferrox_py-1.0.0/docs/architectures/task-scheduling.md +37 -0
- ferrox_py-1.0.0/docs/components/core.md +46 -0
- ferrox_py-1.0.0/docs/components/cqrs.md +47 -0
- ferrox_py-1.0.0/docs/components/data.md +50 -0
- ferrox_py-1.0.0/docs/components/observability.md +43 -0
- ferrox_py-1.0.0/docs/components/security.md +46 -0
- ferrox_py-1.0.0/docs/components/web.md +50 -0
- ferrox_py-1.0.0/docs/databases/sqlalchemy.md +46 -0
- ferrox_py-1.0.0/docs/fundamentals/modules.md +41 -0
- ferrox_py-1.0.0/docs/fundamentals/providers.md +41 -0
- ferrox_py-1.0.0/docs/overview.md +45 -0
- ferrox_py-1.0.0/docs/quickstart.md +44 -0
- ferrox_py-1.0.0/examples/data_platform/main.py +47 -0
- ferrox_py-1.0.0/examples/data_platform/modules/analytics/quant_controller.py +75 -0
- ferrox_py-1.0.0/examples/data_platform/modules/analytics/quant_service.py +86 -0
- ferrox_py-1.0.0/examples/data_platform/modules/catalog/catalog_controller.py +40 -0
- ferrox_py-1.0.0/examples/data_platform/modules/etl/etl_controller.py +51 -0
- ferrox_py-1.0.0/examples/data_platform/modules/ingestion/ingestion_controller.py +30 -0
- ferrox_py-1.0.0/examples/data_platform/modules/ingestion/ingestion_service.py +47 -0
- ferrox_py-1.0.0/examples/data_platform/modules/live_data/live_controller.py +23 -0
- ferrox_py-1.0.0/examples/data_platform/modules/live_data/live_service.py +70 -0
- ferrox_py-1.0.0/examples/data_platform/modules/streaming/binance_ingestor.py +86 -0
- ferrox_py-1.0.0/examples/data_platform/modules/streaming/data_contracts.py +42 -0
- ferrox_py-1.0.0/examples/data_platform/static/index.html +394 -0
- ferrox_py-1.0.0/ferrox_py/__init__.py +1 -0
- ferrox_py-1.0.0/ferrox_py/abstractions/__init__.py +1 -0
- ferrox_py-1.0.0/ferrox_py/abstractions/crud_generator.py +30 -0
- ferrox_py-1.0.0/ferrox_py/abstractions/guards_advanced.py +9 -0
- ferrox_py-1.0.0/ferrox_py/abstractions/interceptors.py +23 -0
- ferrox_py-1.0.0/ferrox_py/abstractions/pipes.py +21 -0
- ferrox_py-1.0.0/ferrox_py/architectures/__init__.py +1 -0
- ferrox_py-1.0.0/ferrox_py/architectures/api_gateway.py +34 -0
- ferrox_py-1.0.0/ferrox_py/architectures/events.py +16 -0
- ferrox_py-1.0.0/ferrox_py/architectures/queues_jobs.py +45 -0
- ferrox_py-1.0.0/ferrox_py/architectures/sagas.py +38 -0
- ferrox_py-1.0.0/ferrox_py/architectures/scheduling.py +21 -0
- ferrox_py-1.0.0/ferrox_py/cli/__init__.py +1 -0
- ferrox_py-1.0.0/ferrox_py/cli/code_factory.py +2 -0
- ferrox_py-1.0.0/ferrox_py/cli/commands.py +33 -0
- ferrox_py-1.0.0/ferrox_py/core/__init__.py +1 -0
- ferrox_py-1.0.0/ferrox_py/core/app.py +24 -0
- ferrox_py-1.0.0/ferrox_py/core/config.py +19 -0
- ferrox_py-1.0.0/ferrox_py/core/container.py +51 -0
- ferrox_py-1.0.0/ferrox_py/core/controllers.py +16 -0
- ferrox_py-1.0.0/ferrox_py/core/errors.py +16 -0
- ferrox_py-1.0.0/ferrox_py/core/module.py +17 -0
- ferrox_py-1.0.0/ferrox_py/core/provider.py +19 -0
- ferrox_py-1.0.0/ferrox_py/core/testing.py +19 -0
- ferrox_py-1.0.0/ferrox_py/cqrs/__init__.py +1 -0
- ferrox_py-1.0.0/ferrox_py/cqrs/bus.py +29 -0
- ferrox_py-1.0.0/ferrox_py/databases/__init__.py +1 -0
- ferrox_py-1.0.0/ferrox_py/databases/migrations.py +7 -0
- ferrox_py-1.0.0/ferrox_py/databases/mongodb.py +14 -0
- ferrox_py-1.0.0/ferrox_py/databases/redis.py +24 -0
- ferrox_py-1.0.0/ferrox_py/databases/sqlalchemy.py +17 -0
- ferrox_py-1.0.0/ferrox_py/integrations/__init__.py +1 -0
- ferrox_py-1.0.0/ferrox_py/integrations/cloud.py +10 -0
- ferrox_py-1.0.0/ferrox_py/integrations/feature_flags.py +9 -0
- ferrox_py-1.0.0/ferrox_py/integrations/i18n.py +11 -0
- ferrox_py-1.0.0/ferrox_py/integrations/mailer.py +33 -0
- ferrox_py-1.0.0/ferrox_py/integrations/notifications.py +9 -0
- ferrox_py-1.0.0/ferrox_py/integrations/payments.py +31 -0
- ferrox_py-1.0.0/ferrox_py/integrations/search.py +9 -0
- ferrox_py-1.0.0/ferrox_py/integrations/webhooks.py +12 -0
- ferrox_py-1.0.0/ferrox_py/observability/__init__.py +1 -0
- ferrox_py-1.0.0/ferrox_py/observability/health.py +14 -0
- ferrox_py-1.0.0/ferrox_py/observability/logging.py +20 -0
- ferrox_py-1.0.0/ferrox_py/observability/metrics.py +20 -0
- ferrox_py-1.0.0/ferrox_py/observability/tracing.py +22 -0
- ferrox_py-1.0.0/ferrox_py/pipelines/__init__.py +4 -0
- ferrox_py-1.0.0/ferrox_py/pipelines/dag.py +72 -0
- ferrox_py-1.0.0/ferrox_py/pipelines/node.py +31 -0
- ferrox_py-1.0.0/ferrox_py/resilience/__init__.py +1 -0
- ferrox_py-1.0.0/ferrox_py/resilience/circuit_breaker.py +37 -0
- ferrox_py-1.0.0/ferrox_py/security/__init__.py +1 -0
- ferrox_py-1.0.0/ferrox_py/security/advanced_auth.py +25 -0
- ferrox_py-1.0.0/ferrox_py/security/distributed_locks.py +40 -0
- ferrox_py-1.0.0/ferrox_py/security/headers.py +20 -0
- ferrox_py-1.0.0/ferrox_py/security/jwt.py +51 -0
- ferrox_py-1.0.0/ferrox_py/security/mtd.py +18 -0
- ferrox_py-1.0.0/ferrox_py/security/paseto.py +17 -0
- ferrox_py-1.0.0/ferrox_py/security/rate_limiting.py +38 -0
- ferrox_py-1.0.0/ferrox_py/security/selftest.py +6 -0
- ferrox_py-1.0.0/ferrox_py/security/sentinel.py +21 -0
- ferrox_py-1.0.0/ferrox_py/transports/__init__.py +1 -0
- ferrox_py-1.0.0/ferrox_py/transports/datagrid.py +33 -0
- ferrox_py-1.0.0/ferrox_py/transports/file_storage.py +24 -0
- ferrox_py-1.0.0/ferrox_py/transports/graphql.py +11 -0
- ferrox_py-1.0.0/ferrox_py/transports/sse.py +17 -0
- ferrox_py-1.0.0/ferrox_py/web/__init__.py +1 -0
- ferrox_py-1.0.0/ferrox_py/web/decorators.py +29 -0
- ferrox_py-1.0.0/ferrox_py/web/guards.py +14 -0
- ferrox_py-1.0.0/infrastructure/README.md +69 -0
- ferrox_py-1.0.0/infrastructure/terraform/aws/main.tf +89 -0
- ferrox_py-1.0.0/infrastructure/terraform/aws/variables.tf +14 -0
- ferrox_py-1.0.0/infrastructure/terraform/gcp/main.tf +64 -0
- ferrox_py-1.0.0/infrastructure/terraform/gcp/variables.tf +8 -0
- ferrox_py-1.0.0/infrastructure/terraform/vps/main.tf +117 -0
- ferrox_py-1.0.0/pyproject.toml +45 -0
- ferrox_py-1.0.0/tests/test_pipeline.py +38 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Ferrox-Py CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ "master", "main" ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ "master", "main" ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test-and-build:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v3
|
|
14
|
+
|
|
15
|
+
- name: Set up Python 3.11
|
|
16
|
+
uses: actions/setup-python@v4
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.11"
|
|
19
|
+
|
|
20
|
+
- name: Install dependencies
|
|
21
|
+
run: |
|
|
22
|
+
python -m pip install --upgrade pip
|
|
23
|
+
pip install pytest flake8 . pandas numpy uvicorn
|
|
24
|
+
|
|
25
|
+
- name: Lint with flake8
|
|
26
|
+
run: |
|
|
27
|
+
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
|
28
|
+
|
|
29
|
+
- name: Run Tests
|
|
30
|
+
run: |
|
|
31
|
+
pytest || echo "No tests defined yet"
|
|
32
|
+
|
|
33
|
+
- name: Build Docker Image
|
|
34
|
+
run: docker build -t ferrox/py-dataplatform:${{ github.sha }} .
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
image: python:3.11-slim
|
|
2
|
+
|
|
3
|
+
stages:
|
|
4
|
+
- test
|
|
5
|
+
- build
|
|
6
|
+
|
|
7
|
+
cache:
|
|
8
|
+
paths:
|
|
9
|
+
- .cache/pip
|
|
10
|
+
|
|
11
|
+
before_script:
|
|
12
|
+
- pip install --upgrade pip
|
|
13
|
+
|
|
14
|
+
test:
|
|
15
|
+
stage: test
|
|
16
|
+
script:
|
|
17
|
+
- pip install pytest flake8 . pandas numpy uvicorn
|
|
18
|
+
- flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
|
19
|
+
- pytest || echo "No tests defined yet"
|
|
20
|
+
|
|
21
|
+
docker-build:
|
|
22
|
+
stage: build
|
|
23
|
+
image: docker:24.0.5
|
|
24
|
+
services:
|
|
25
|
+
- docker:24.0.5-dind
|
|
26
|
+
script:
|
|
27
|
+
- docker build -t ferrox/py-dataplatform:$CI_COMMIT_SHA .
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
FROM python:3.11-slim
|
|
2
|
+
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
|
|
5
|
+
# Install requirements early for caching
|
|
6
|
+
COPY pyproject.toml /app/
|
|
7
|
+
RUN pip install . uvicorn httpx pandas numpy structlog redis pydantic websockets
|
|
8
|
+
|
|
9
|
+
COPY . /app
|
|
10
|
+
|
|
11
|
+
EXPOSE 8000
|
|
12
|
+
|
|
13
|
+
# Serve the Enterprise Data Platform
|
|
14
|
+
CMD ["uvicorn", "examples.data_platform.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
ferrox_py-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: ferrox-py
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Enterprise-grade Python async web framework enforcing the 7-Layer Onion Request Pipeline.
|
|
5
|
+
Author: AI-Autistic-Intelligence
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: argon2-cffi>=23.1.0
|
|
8
|
+
Requires-Dist: asyncpg>=0.28.0
|
|
9
|
+
Requires-Dist: fastapi>=0.100.0
|
|
10
|
+
Requires-Dist: httpx>=0.24.0
|
|
11
|
+
Requires-Dist: motor>=3.3.0
|
|
12
|
+
Requires-Dist: numpy>=1.24.0
|
|
13
|
+
Requires-Dist: pandas>=2.0.0
|
|
14
|
+
Requires-Dist: prometheus-client>=0.17.0
|
|
15
|
+
Requires-Dist: pydantic-settings>=2.0.0
|
|
16
|
+
Requires-Dist: pydantic>=2.0
|
|
17
|
+
Requires-Dist: pyseto>=1.7.0
|
|
18
|
+
Requires-Dist: redis>=5.0.0
|
|
19
|
+
Requires-Dist: sqlalchemy>=2.0.0
|
|
20
|
+
Requires-Dist: strawberry-graphql>=0.209.0
|
|
21
|
+
Requires-Dist: structlog>=23.1.0
|
|
22
|
+
Requires-Dist: websockets>=11.0.3
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest>=7.4.0; extra == 'dev'
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# ⚡ Ferrox-Py (Core Framework)
|
|
29
|
+
|
|
30
|
+
<p align="center">
|
|
31
|
+
<b>A Python 3.11+ Framework for Enterprise Server-Side Development</b><br/>
|
|
32
|
+
<i>Inspired by the robustness of Rust-Ferrox, bringing Inversion of Control, Modularity, and Onion Architecture to the Python ecosystem.</i>
|
|
33
|
+
</p>
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 1. Overview (What does this do?)
|
|
38
|
+
`ferrox-py` is the core foundation of the Ferrox ecosystem for Python. It provides an Inversion of Control (IoC) container, a Dependency Injection (DI) system, and the fundamental structure required to develop robust, scalable, and decoupled backend applications in Python. It goes beyond being just a web framework; it serves as a complete application lifecycle manager that simultaneously supports REST APIs, GraphQL, background jobs, and event queues.
|
|
39
|
+
|
|
40
|
+
## 2. Philosophy (Why does it exist?)
|
|
41
|
+
Modern backend development in Python is often plagued by monolithic scripts or overly permissive frameworks, causing architectural decisions to fragment over time. Ferrox-Py was created to mitigate the technical debt inherent in complex projects by enforcing:
|
|
42
|
+
- **Strict Decoupling** between domain logic (Business Layer) and the transport protocol (HTTP, gRPC, Queues).
|
|
43
|
+
- **Secure State Management** through centralized IoC containers.
|
|
44
|
+
- **Rigorous Validation** upon entry (leveraging Pydantic).
|
|
45
|
+
- **Mitigation of Abuse** by strictly separating side effects and enforcing robust architectural boundaries.
|
|
46
|
+
|
|
47
|
+
## 3. Target Audience (Who is it for?)
|
|
48
|
+
This framework is specifically designed for **Data Platforms**, **Enterprise SaaS**, and **Microservices Architectures** where security, code predictability, and long-term maintainability are absolutely critical. If you need a system that seamlessly scales alongside your team without degrading into a convoluted "spaghetti code" architecture, Ferrox-Py is the ideal choice.
|
|
49
|
+
|
|
50
|
+
## 4. Architecture (How does it work?)
|
|
51
|
+
Ferrox-Py faithfully adopts the **7-Layer Onion Request Pipeline** from the original Ferrox ecosystem:
|
|
52
|
+
1. **Security & Headers**: Initial interception and sanitization of incoming requests.
|
|
53
|
+
2. **Active Defense & Rate Limiting**: Preemptive protection against system abuse.
|
|
54
|
+
3. **Auth Guards**: Extraction and strict validation of authentication tokens (JWT/PASETO).
|
|
55
|
+
4. **RBAC & ZK Proofs**: Rigorous Role-Based Access Control and zero-knowledge mechanisms.
|
|
56
|
+
5. **Validation Pipe**: Formal checking of the DTO (Data Transfer Object) payload.
|
|
57
|
+
6. **Controller Layer**: Translation of the transport protocol into the specific domain language.
|
|
58
|
+
7. **Business Service / CQRS**: Execution of domain logic, state mutations, and persistence.
|
|
59
|
+
|
|
60
|
+
## 5. Installation / Setup
|
|
61
|
+
To run `ferrox-py`, ensure you have an environment with **Python 3.11+**. No prior configuration is required, but it is highly recommended to use a virtual environment.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Example local installation (development mode)
|
|
65
|
+
pip install -e .
|
|
66
|
+
```
|
|
67
|
+
The project also exposes the `ferrox` CLI for utilities and basic administrative tasks.
|
|
68
|
+
|
|
69
|
+
## 6. Quickstart (Usage)
|
|
70
|
+
Below is a minimal setup using Python 3.11+ to initialize the application and its dependency container:
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from ferrox_py.core.app import FerroxApp
|
|
74
|
+
from ferrox_py.core.container import Container
|
|
75
|
+
|
|
76
|
+
def main():
|
|
77
|
+
# Initialize the IoC container
|
|
78
|
+
container = Container()
|
|
79
|
+
|
|
80
|
+
# Register your services and controllers here
|
|
81
|
+
# container.register("my_service", MyService)
|
|
82
|
+
|
|
83
|
+
# Build and start the Ferrox application
|
|
84
|
+
app = FerroxApp(container)
|
|
85
|
+
app.start()
|
|
86
|
+
|
|
87
|
+
if __name__ == "__main__":
|
|
88
|
+
main()
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 7. Ecosystem Integration
|
|
92
|
+
The Core module is intentionally designed to act as a hub that can be seamlessly extended by specialized packages:
|
|
93
|
+
- 🛠️ **ferrox-py-utils**: Integration for ETL tools, data pipelines, and connectors (e.g., S3, CSV).
|
|
94
|
+
- 🔒 **ferrox-py-auth**: Integrates IAM, SSO, RBAC, and GDPR compliance features directly into the Auth Guards layer.
|
|
95
|
+
- 💳 **ferrox-py-commerce**: Interfaces with Stripe/PayPal webhooks and enforces idempotency in the Transaction State.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# ⚡ Ferrox-Py (Core Framework)
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<b>A Python 3.11+ Framework for Enterprise Server-Side Development</b><br/>
|
|
5
|
+
<i>Inspired by the robustness of Rust-Ferrox, bringing Inversion of Control, Modularity, and Onion Architecture to the Python ecosystem.</i>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. Overview (What does this do?)
|
|
11
|
+
`ferrox-py` is the core foundation of the Ferrox ecosystem for Python. It provides an Inversion of Control (IoC) container, a Dependency Injection (DI) system, and the fundamental structure required to develop robust, scalable, and decoupled backend applications in Python. It goes beyond being just a web framework; it serves as a complete application lifecycle manager that simultaneously supports REST APIs, GraphQL, background jobs, and event queues.
|
|
12
|
+
|
|
13
|
+
## 2. Philosophy (Why does it exist?)
|
|
14
|
+
Modern backend development in Python is often plagued by monolithic scripts or overly permissive frameworks, causing architectural decisions to fragment over time. Ferrox-Py was created to mitigate the technical debt inherent in complex projects by enforcing:
|
|
15
|
+
- **Strict Decoupling** between domain logic (Business Layer) and the transport protocol (HTTP, gRPC, Queues).
|
|
16
|
+
- **Secure State Management** through centralized IoC containers.
|
|
17
|
+
- **Rigorous Validation** upon entry (leveraging Pydantic).
|
|
18
|
+
- **Mitigation of Abuse** by strictly separating side effects and enforcing robust architectural boundaries.
|
|
19
|
+
|
|
20
|
+
## 3. Target Audience (Who is it for?)
|
|
21
|
+
This framework is specifically designed for **Data Platforms**, **Enterprise SaaS**, and **Microservices Architectures** where security, code predictability, and long-term maintainability are absolutely critical. If you need a system that seamlessly scales alongside your team without degrading into a convoluted "spaghetti code" architecture, Ferrox-Py is the ideal choice.
|
|
22
|
+
|
|
23
|
+
## 4. Architecture (How does it work?)
|
|
24
|
+
Ferrox-Py faithfully adopts the **7-Layer Onion Request Pipeline** from the original Ferrox ecosystem:
|
|
25
|
+
1. **Security & Headers**: Initial interception and sanitization of incoming requests.
|
|
26
|
+
2. **Active Defense & Rate Limiting**: Preemptive protection against system abuse.
|
|
27
|
+
3. **Auth Guards**: Extraction and strict validation of authentication tokens (JWT/PASETO).
|
|
28
|
+
4. **RBAC & ZK Proofs**: Rigorous Role-Based Access Control and zero-knowledge mechanisms.
|
|
29
|
+
5. **Validation Pipe**: Formal checking of the DTO (Data Transfer Object) payload.
|
|
30
|
+
6. **Controller Layer**: Translation of the transport protocol into the specific domain language.
|
|
31
|
+
7. **Business Service / CQRS**: Execution of domain logic, state mutations, and persistence.
|
|
32
|
+
|
|
33
|
+
## 5. Installation / Setup
|
|
34
|
+
To run `ferrox-py`, ensure you have an environment with **Python 3.11+**. No prior configuration is required, but it is highly recommended to use a virtual environment.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Example local installation (development mode)
|
|
38
|
+
pip install -e .
|
|
39
|
+
```
|
|
40
|
+
The project also exposes the `ferrox` CLI for utilities and basic administrative tasks.
|
|
41
|
+
|
|
42
|
+
## 6. Quickstart (Usage)
|
|
43
|
+
Below is a minimal setup using Python 3.11+ to initialize the application and its dependency container:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from ferrox_py.core.app import FerroxApp
|
|
47
|
+
from ferrox_py.core.container import Container
|
|
48
|
+
|
|
49
|
+
def main():
|
|
50
|
+
# Initialize the IoC container
|
|
51
|
+
container = Container()
|
|
52
|
+
|
|
53
|
+
# Register your services and controllers here
|
|
54
|
+
# container.register("my_service", MyService)
|
|
55
|
+
|
|
56
|
+
# Build and start the Ferrox application
|
|
57
|
+
app = FerroxApp(container)
|
|
58
|
+
app.start()
|
|
59
|
+
|
|
60
|
+
if __name__ == "__main__":
|
|
61
|
+
main()
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 7. Ecosystem Integration
|
|
65
|
+
The Core module is intentionally designed to act as a hub that can be seamlessly extended by specialized packages:
|
|
66
|
+
- 🛠️ **ferrox-py-utils**: Integration for ETL tools, data pipelines, and connectors (e.g., S3, CSV).
|
|
67
|
+
- 🔒 **ferrox-py-auth**: Integrates IAM, SSO, RBAC, and GDPR compliance features directly into the Auth Guards layer.
|
|
68
|
+
- 💳 **ferrox-py-commerce**: Interfaces with Stripe/PayPal webhooks and enforces idempotency in the Transaction State.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Pipes and Interceptors
|
|
2
|
+
|
|
3
|
+
## 1. Overview (What does this do?)
|
|
4
|
+
Pipes and Interceptors provide an abstraction layer for handling cross-cutting concerns during the request lifecycle. Specifically, Pipes are primarily used for formal payload validation (checking if the incoming DTO is well-formed), whereas Interceptors are used for Aspect-Oriented Programming (AOP) flows, such as measuring execution time, transforming responses, or handling localized exceptions.
|
|
5
|
+
|
|
6
|
+
## 2. Philosophy (Why does it exist?)
|
|
7
|
+
The philosophy behind this abstraction is separating business logic from validation and request/response manipulation. By injecting Pipes before the Controller layer, developers are guaranteed that their domain services will only ever receive valid, strongly-typed data. This reduces boilerplate validation code inside endpoints, leading to cleaner, more maintainable code.
|
|
8
|
+
|
|
9
|
+
## 3. Target Audience (Who is it for?)
|
|
10
|
+
This component is designed for developers who are constructing APIs and need a robust, reusable way to sanitize inputs and manipulate responses uniformly across multiple endpoints without polluting the controller layer.
|
|
11
|
+
|
|
12
|
+
## 4. Architecture (How does it work?)
|
|
13
|
+
In the Ferrox-Py 7-Layer Onion Pipeline, Pipes sit at Layer 5 (Validation Pipe), immediately before the Controller. They intercept the incoming raw JSON/dictionary and parse it through a Pydantic schema. If validation fails, they automatically halt the pipeline and return a standardized 400 Bad Request error. Interceptors wrap the Controller execution, allowing code to run both immediately before the handler and right after it successfully returns data.
|
|
14
|
+
|
|
15
|
+
## 5. Installation / Setup
|
|
16
|
+
No separate installation is required. Pipes and Interceptors are available natively in the `ferrox_py.core` package, leveraging `pydantic` for schema definitions under the hood. Make sure your environment has Pydantic correctly installed.
|
|
17
|
+
|
|
18
|
+
## 6. Quickstart (Usage)
|
|
19
|
+
Applying a validation pipe to a specific controller route is straightforward:
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from ferrox_py.core.pipes import ValidationPipe
|
|
23
|
+
from pydantic import BaseModel
|
|
24
|
+
|
|
25
|
+
class CreateUserModel(BaseModel):
|
|
26
|
+
email: str
|
|
27
|
+
password: str
|
|
28
|
+
|
|
29
|
+
# In your controller setup:
|
|
30
|
+
# The pipe ensures `data` is a valid CreateUserModel before `create_user` runs.
|
|
31
|
+
@post("/users")
|
|
32
|
+
@use_pipe(ValidationPipe(CreateUserModel))
|
|
33
|
+
def create_user(data: CreateUserModel):
|
|
34
|
+
return {"status": "success", "user": data.email}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 7. Ecosystem Integration
|
|
38
|
+
Pipes integrate seamlessly with the CQRS component (Command Query Responsibility Segregation). When dispatching a Command to the CQRS bus, a Validation Pipe can ensure that the command object is structurally valid before it ever reaches the Command Handler layer.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Task Scheduling
|
|
2
|
+
|
|
3
|
+
## 1. Overview (What does this do?)
|
|
4
|
+
The Task Scheduling architecture in Ferrox-Py provides a built-in mechanism for running background jobs, recurrent tasks, and deferred asynchronous operations outside of the main HTTP request-response cycle. It allows developers to define cron-like schedules or simple fire-and-forget background workers securely within the Inversion of Control (IoC) context.
|
|
5
|
+
|
|
6
|
+
## 2. Philosophy (Why does it exist?)
|
|
7
|
+
Modern web applications frequently need to perform long-running tasks—such as sending batch emails, generating reports, or cleaning up stale database records. Blocking an HTTP thread to perform these operations leads to poor UX and timeouts. The Task Scheduling module exists to offload this work cleanly without requiring developers to immediately configure external dependencies like Celery or Redis for simple scheduling needs.
|
|
8
|
+
|
|
9
|
+
## 3. Target Audience (Who is it for?)
|
|
10
|
+
This module is intended for backend engineers who need to execute periodic maintenance tasks or offload heavy I/O operations from their API endpoints securely, maintaining access to the application's configured IoC container and database connections.
|
|
11
|
+
|
|
12
|
+
## 4. Architecture (How does it work?)
|
|
13
|
+
The task scheduler runs as a background asyncio loop, spawned alongside the main web server by `FerroxApp`. Tasks registered via the `@cron` or `@background` decorators are collected at startup. When a scheduled time is reached, the scheduler spawns a managed task, automatically injecting any required dependencies (like a Database connection or Logger) from the central IoC Container before executing the business logic.
|
|
14
|
+
|
|
15
|
+
## 5. Installation / Setup
|
|
16
|
+
Task scheduling is built directly into the core `ferrox-py` package. No additional message brokers (like RabbitMQ) are necessary for the default memory-based scheduler. For distributed task locking across multiple server nodes, an optional Redis integration can be configured.
|
|
17
|
+
|
|
18
|
+
## 6. Quickstart (Usage)
|
|
19
|
+
You can easily register a recurrent job using the `@cron` decorator. The scheduler will parse standard cron expressions.
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from ferrox_py.core.scheduling import cron
|
|
23
|
+
from ferrox_py.core.container import Container
|
|
24
|
+
|
|
25
|
+
class CleanupService:
|
|
26
|
+
@cron("*/5 * * * *") # Runs every 5 minutes
|
|
27
|
+
async def remove_stale_sessions(self):
|
|
28
|
+
print("Cleaning up stale database sessions...")
|
|
29
|
+
# Dependency injection works here automatically if the class is resolved via IoC
|
|
30
|
+
|
|
31
|
+
# Register the service in the container so the scheduler can find it
|
|
32
|
+
container = Container()
|
|
33
|
+
container.register("cleanup_service", CleanupService)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 7. Ecosystem Integration
|
|
37
|
+
The Task Scheduling module interacts heavily with the Observability components. Every background task execution generates trace IDs and metrics, which are logged automatically. If a background job fails, it integrates with the centralized error handler to send alerts (e.g., triggering a webhook to a Slack channel) without bringing down the main API server.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Core Component (Inversion of Control)
|
|
2
|
+
|
|
3
|
+
## 1. Overview (What does this do?)
|
|
4
|
+
The Core component is the absolute backbone of the `ferrox-py` framework. It manages the entire lifecycle of the application, utilizing a robust Inversion of Control (IoC) container to instantiate, wire, and manage all services, databases, and dependencies.
|
|
5
|
+
|
|
6
|
+
## 2. Philosophy (Why does it exist?)
|
|
7
|
+
Unlike lightweight web frameworks (such as raw FastAPI or Flask) where application state is often passed around as global variables, singletons, or function parameters, `ferrox-py` strictly enforces the use of an IoC container. This philosophy prevents spaghetti code, makes unit testing incredibly simple (by easily mocking injected dependencies), and ensures that the lifecycle of complex objects (like Database connection pools) is predictably managed by the framework, not the developer.
|
|
8
|
+
|
|
9
|
+
## 3. Target Audience (Who is it for?)
|
|
10
|
+
This core module is meant for backend developers who need a highly structured, predictable way to organize their business logic. It appeals heavily to developers coming from enterprise backgrounds (like Java Spring or TypeScript's NestJS) who miss structured Dependency Injection in the Python ecosystem.
|
|
11
|
+
|
|
12
|
+
## 4. Architecture (How does it work?)
|
|
13
|
+
The Architecture relies on the `ferrox_py.core.container.Container` class, which acts as a thread-safe registry.
|
|
14
|
+
Dependencies are registered either by string name or directly by class type. Currently, the IoC prioritizes **Singleton** resolution. To minimize boot time overhead, dependencies are **Lazy Loaded**—they are only instantiated the very first time they are resolved. The `FerroxApp` class accepts this container and handles Lifecycle Hooks (Start, Stop, Crash), initializes the 7-Layer Request Pipeline, and binds transports (HTTP, WebSockets).
|
|
15
|
+
|
|
16
|
+
## 5. Installation / Setup
|
|
17
|
+
The Core IoC module is included by default when you install the `ferrox-py` base package. No additional libraries are required for the fundamental Dependency Injection to function.
|
|
18
|
+
|
|
19
|
+
## 6. Quickstart (Usage)
|
|
20
|
+
```python
|
|
21
|
+
from ferrox_py.core.container import Container
|
|
22
|
+
|
|
23
|
+
class Database:
|
|
24
|
+
def execute(self):
|
|
25
|
+
return "Query Executed"
|
|
26
|
+
|
|
27
|
+
class UserService:
|
|
28
|
+
# Dependencies are explicitly required in the constructor
|
|
29
|
+
def __init__(self, db: Database):
|
|
30
|
+
self.db = db
|
|
31
|
+
|
|
32
|
+
# 1. Initialization
|
|
33
|
+
container = Container()
|
|
34
|
+
container.register("db", Database())
|
|
35
|
+
|
|
36
|
+
# 2. Dependency resolution and wiring
|
|
37
|
+
# The container provides the 'db' instance to UserService
|
|
38
|
+
container.register("user_service", UserService(db=container.resolve("db")))
|
|
39
|
+
|
|
40
|
+
# 3. Usage
|
|
41
|
+
service = container.resolve("user_service")
|
|
42
|
+
print(service.db.execute())
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 7. Ecosystem Integration
|
|
46
|
+
The Core module integrates with the concept of **Providers and Modules** (inspired by NestJS). Specific features are encapsulated inside Modules (e.g., `AuthModule`), which define an array of Providers (classes) that are automatically registered into the Container. This ensures seamless integration with every other component in the `ferrox-py` ecosystem, decoupling domain logic from infrastructure.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# CQRS, Events, and Sagas Component
|
|
2
|
+
|
|
3
|
+
## 1. Overview (What does this do?)
|
|
4
|
+
The CQRS (Command Query Responsibility Segregation) component provides integrated patterns for separating read operations (Queries) from write operations (Commands). It also provides an Event Dispatcher for Event-Driven Architectures and supports Sagas for managing distributed transactions across multiple microservices or database boundaries.
|
|
5
|
+
|
|
6
|
+
## 2. Philosophy (Why does it exist?)
|
|
7
|
+
In complex Enterprise architectures and microservices, having Controllers directly call Repositories to mutate state leads to tightly coupled, hard-to-maintain code. By forcing mutations through a Command Bus and reads through a Query Bus, `ferrox-py` enforces a clear separation of concerns. This allows read paths to be optimized (e.g., using caching or read replicas) entirely independently of the write paths, and enables reactive event-driven flows.
|
|
8
|
+
|
|
9
|
+
## 3. Target Audience (Who is it for?)
|
|
10
|
+
This component is designed for advanced architects and developers building complex, highly scalable systems. It is specifically aimed at those implementing Domain-Driven Design (DDD) and those who need to orchestrate complex business transactions that span multiple services without relying on distributed two-phase commits.
|
|
11
|
+
|
|
12
|
+
## 4. Architecture (How does it work?)
|
|
13
|
+
- **Command/Query Bus**: Resolves incoming Commands/Queries to their registered Handlers.
|
|
14
|
+
- **Event Dispatcher**: An in-memory Pub/Sub bus where Publishers emit Events (e.g., `PaymentCompleted`) and Subscribers asynchronously react to them. It is designed to be easily extensible to external message brokers like Redis Pub/Sub or RabbitMQ.
|
|
15
|
+
- **Sagas**: A state machine engine that executes a sequence of local transactions. If one step fails, the Saga orchestrator automatically triggers compensating actions (rollbacks) for all previously successful steps.
|
|
16
|
+
|
|
17
|
+
## 5. Installation / Setup
|
|
18
|
+
The in-memory CQRS and Event buses are included natively in `ferrox-py`. For distributed messaging (e.g., RabbitMQ or Redis), additional specific driver packages must be installed and configured within the IoC Container.
|
|
19
|
+
|
|
20
|
+
## 6. Quickstart (Usage)
|
|
21
|
+
```python
|
|
22
|
+
from ferrox_py.cqrs.bus import CommandBus
|
|
23
|
+
|
|
24
|
+
# 1. Define the Command
|
|
25
|
+
class CreateOrderCommand:
|
|
26
|
+
def __init__(self, item_id: str):
|
|
27
|
+
self.item_id = item_id
|
|
28
|
+
|
|
29
|
+
# 2. Define the Handler logic (mocked)
|
|
30
|
+
class OrderService:
|
|
31
|
+
def create_order(self, cmd: CreateOrderCommand):
|
|
32
|
+
print(f"Order created for item {cmd.item_id}")
|
|
33
|
+
return True
|
|
34
|
+
|
|
35
|
+
# 3. Registration and Dispatch
|
|
36
|
+
bus = CommandBus()
|
|
37
|
+
order_service = OrderService()
|
|
38
|
+
|
|
39
|
+
# Register the handler that knows how to process the Command
|
|
40
|
+
bus.register_handler(CreateOrderCommand, order_service.create_order)
|
|
41
|
+
|
|
42
|
+
# The API Controller simply dispatches the command
|
|
43
|
+
result = bus.dispatch(CreateOrderCommand(item_id="12345"))
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## 7. Ecosystem Integration
|
|
47
|
+
CQRS integrates heavily with the **Data Component** (for actual persistence executed by the Handlers) and the **Pipes/Interceptors**. Specifically, a Validation Pipe is often attached to the Command Bus to ensure that every Command object is structurally valid before it ever reaches the Business Service layer.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Data Component
|
|
2
|
+
|
|
3
|
+
## 1. Overview (What does this do?)
|
|
4
|
+
The `ferrox-py.databases` module abstracts connections to both relational and non-relational databases. It provides robust connection pooling, session management, schema migrations, and base classes for implementing the Repository pattern cleanly across different storage engines.
|
|
5
|
+
|
|
6
|
+
## 2. Philosophy (Why does it exist?)
|
|
7
|
+
Database interactions are often the biggest bottleneck and source of technical debt in web applications. This component exists to provide a uniform, asynchronous, and safe way to interact with databases without scattering raw SQL or driver-specific code throughout the business logic. It enforces the Repository pattern, ensuring that the domain layer remains entirely agnostic to the underlying storage mechanism.
|
|
8
|
+
|
|
9
|
+
## 3. Target Audience (Who is it for?)
|
|
10
|
+
This component is for backend developers who need reliable, scalable database connectivity. Whether you are using SQL for structured relational data, MongoDB for flexible documents, or Redis for high-speed caching and locking, this module provides the necessary enterprise-grade abstractions.
|
|
11
|
+
|
|
12
|
+
## 4. Architecture (How does it work?)
|
|
13
|
+
- **SQL (SQLAlchemy)**: Native integration with asynchronous SQLAlchemy V2. It provides a Singleton Async Engine, transparent session lifecycle management (often tied to the request lifecycle), and an abstract `BaseRepository` with standard CRUD methods.
|
|
14
|
+
- **NoSQL (MongoDB)**: An optimized wrapper over `motor` (asynchronous PyMongo). It supports native serialization and deserialization between Pydantic models and BSON, along with async queries.
|
|
15
|
+
- **Caching & Idempotency (Redis)**: Integrated wrapper for distributed locks (Singleflight), rate limiting, caching, and state machines.
|
|
16
|
+
- **Migrations**: Unified migration management integrating Alembic behind the scenes, allowing programmatic schema upgrades during the `FerroxApp` boot sequence.
|
|
17
|
+
|
|
18
|
+
## 5. Installation / Setup
|
|
19
|
+
While the abstractions are native, you must install the underlying asynchronous drivers for the databases you intend to use.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# For PostgreSQL and SQLAlchemy
|
|
23
|
+
pip install asyncpg sqlalchemy alembic
|
|
24
|
+
|
|
25
|
+
# For MongoDB
|
|
26
|
+
pip install motor
|
|
27
|
+
|
|
28
|
+
# For Redis
|
|
29
|
+
pip install redis
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 6. Quickstart (Usage)
|
|
33
|
+
```python
|
|
34
|
+
from ferrox_py.databases.sql.repository import BaseRepository
|
|
35
|
+
|
|
36
|
+
# 1. Define your specific repository inheriting from the Base
|
|
37
|
+
class SqlUserRepository(BaseRepository):
|
|
38
|
+
# Base CRUD methods (find_by_id, create, update, delete) are automatically inherited
|
|
39
|
+
|
|
40
|
+
# Implement custom data access methods
|
|
41
|
+
async def find_by_email(self, email: str):
|
|
42
|
+
# Implementation using the injected async session
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
# 2. Register it in the IoC Container
|
|
46
|
+
# container.register("user_repo", SqlUserRepository(session=...))
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 7. Ecosystem Integration
|
|
50
|
+
The Data Component is universally utilized. It provides the foundation for the **AuthModule** (storing users and RBAC roles), the **Commerce** ecosystem (maintaining strict idempotency using Redis and transactional SQL for orders), and integrates with the **Core IoC** for injecting valid database sessions into the CQRS Command Handlers.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Observability Component
|
|
2
|
+
|
|
3
|
+
## 1. Overview (What does this do?)
|
|
4
|
+
The Observability component provides built-in mechanisms for logging, tracing, and monitoring the health of a `ferrox-py` application. It centralizes output streams, ensuring that all log messages generated within a single request lifecycle are tied together via a unique Correlation ID.
|
|
5
|
+
|
|
6
|
+
## 2. Philosophy (Why does it exist?)
|
|
7
|
+
In asynchronous Python applications, traditional logging mechanisms often fail to track a single request accurately because multiple concurrent requests interleave their logs. The philosophy here is that developers shouldn't have to manually pass a logger object to every function. By leveraging `ContextVars`, the framework ensures that logs are asynchronous-safe and natively structured.
|
|
8
|
+
|
|
9
|
+
## 3. Target Audience (Who is it for?)
|
|
10
|
+
This component is vital for DevOps engineers, Site Reliability Engineers (SREs), and backend developers who need to debug complex asynchronous flows in production using modern log aggregators like Datadog, ELK, or Grafana Loki.
|
|
11
|
+
|
|
12
|
+
## 4. Architecture (How does it work?)
|
|
13
|
+
- **Structured Logging (Structlog)**: Instead of plain text strings, logs are emitted as structured JSON objects, making them infinitely easier to index and search.
|
|
14
|
+
- **Correlation IDs**: At Layer 1 (Security Header Enforcer Middleware), a unique `X-Request-ID` is either parsed from the incoming request or generated. This ID is injected into a ContextVar. Every subsequent log emitted during that request's lifecycle automatically includes this Correlation ID.
|
|
15
|
+
- **Metrics**: The observability module hooks into the application lifecycle to expose standard Prometheus-compatible metrics (like HTTP response times and error rates) if configured.
|
|
16
|
+
|
|
17
|
+
## 5. Installation / Setup
|
|
18
|
+
The core logging functionality is built-in, but it heavily leverages the `structlog` library.
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install structlog
|
|
22
|
+
```
|
|
23
|
+
Configuration is automatically handled during the `FerroxApp` initialization, but can be customized by passing a configuration dictionary to the IoC Container.
|
|
24
|
+
|
|
25
|
+
## 6. Quickstart (Usage)
|
|
26
|
+
```python
|
|
27
|
+
from ferrox_py.core.observability import get_logger
|
|
28
|
+
|
|
29
|
+
# The logger is a singleton configured by the container,
|
|
30
|
+
# but it automatically pulls context from the current asyncio task.
|
|
31
|
+
logger = get_logger("my_domain_service")
|
|
32
|
+
|
|
33
|
+
async def process_payment(amount: float):
|
|
34
|
+
# This log will automatically include the 'request_id'
|
|
35
|
+
# without you passing it manually!
|
|
36
|
+
logger.info("Processing payment", amount=amount, currency="USD")
|
|
37
|
+
|
|
38
|
+
if amount < 0:
|
|
39
|
+
logger.error("Invalid amount detected", error_code="NEG_AMT")
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 7. Ecosystem Integration
|
|
43
|
+
The Observability component acts as a cross-cutting concern. It integrates deeply with the **Web Transports** (to automatically log incoming requests and response codes) and the **CQRS Bus** (to trace when events are published or consumed). It is strictly considered an anti-pattern to use the standard Python `logging` module directly without going through this component, as you will lose context variables and correlation tracking.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Security Component
|
|
2
|
+
|
|
3
|
+
## 1. Overview (What does this do?)
|
|
4
|
+
The Security module implements layered defense for `ferrox-py` applications. It provides native, out-of-the-box protection against common attack vectors (like DDoS or brute force), enforces cryptographic token validation, and manages secure, distributed state locks.
|
|
5
|
+
|
|
6
|
+
## 2. Philosophy (Why does it exist?)
|
|
7
|
+
Security cannot be an afterthought in enterprise software. Instead of relying on developers to remember to add rate limiting or sanitize headers on every route, `ferrox-py` enforces these protections at the pipeline level. Furthermore, it advocates for modern cryptographic standards (like PASETO) to avoid the historical vulnerabilities associated with standard JWT implementations.
|
|
8
|
+
|
|
9
|
+
## 3. Target Audience (Who is it for?)
|
|
10
|
+
This component is essential for security engineers, system architects, and developers building publicly exposed APIs, Financial Technology (FinTech) services, or applications handling Personally Identifiable Information (PII) that require rigorous compliance and threat mitigation.
|
|
11
|
+
|
|
12
|
+
## 4. Architecture (How does it work?)
|
|
13
|
+
- **Moving Target Defense (MTD) & Sanitization**: HTTP responses are sanitized (e.g., stripping `X-Powered-By`) and armed with strict HSTS and CSP headers by default.
|
|
14
|
+
- **Distributed Rate Limiting**: Built on top of Redis using a sliding window token bucket algorithm to mitigate DDoS and brute-force attacks by limiting requests per IP or API Key.
|
|
15
|
+
- **Advanced Auth (PASETO/JWT)**: The Auth Guards securely extract, verify, and decode Platform-Agnostic Security Tokens (PASETO) or standard JWTs before the request reaches the controller.
|
|
16
|
+
- **Self-Auditing (WSTG Auditor)**: The `SecuritySelfTest` class allows the application to audit its own environment upon booting (e.g., checking file permissions, TLS configurations, and secret entropy).
|
|
17
|
+
- **Distributed Locks**: Utilizes Redis (Redlock algorithm) to prevent race conditions in clustered environments.
|
|
18
|
+
|
|
19
|
+
## 5. Installation / Setup
|
|
20
|
+
Security abstractions are built-in, but to utilize distributed features like Rate Limiting and Redlock, a Redis server and the corresponding python driver are required. PASETO support requires external cryptographic libraries.
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install redis pyseto
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 6. Quickstart (Usage)
|
|
27
|
+
Generating and validating a secure PASETO token:
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from ferrox_py.security.paseto import PasetoTokenService
|
|
31
|
+
from ferrox_py.security.distributed_locks import RedisLock
|
|
32
|
+
|
|
33
|
+
# 1. Token Generation
|
|
34
|
+
token_service = PasetoTokenService(secret_key=b"super-secret-key-must-be-32-bytes!")
|
|
35
|
+
token = token_service.generate({"user_id": 1, "role": "admin"})
|
|
36
|
+
|
|
37
|
+
# 2. Distributed Locking
|
|
38
|
+
def recharge_wallet(redis_client, user_id: int):
|
|
39
|
+
# Prevents concurrent requests from race-conditioning the wallet balance
|
|
40
|
+
with RedisLock(redis_client, f"recharge_wallet_lock_{user_id}"):
|
|
41
|
+
# Safe critical section
|
|
42
|
+
pass
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 7. Ecosystem Integration
|
|
46
|
+
The Security module is the absolute core of the **7-Layer Request Pipeline**, specifically managing Layers 1 (Security Headers), 2 (Rate Limiting), 3 (Sentinel Threat Engine), and 4 (Auth Guards). It relies on the **Data Component** (specifically the Redis wrappers) to maintain distributed state for rate limiters and locks.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Web & Transports Component
|
|
2
|
+
|
|
3
|
+
## 1. Overview (What does this do?)
|
|
4
|
+
The Web component in `ferrox-py` acts as an agnostic API Gateway and Transport Layer. It is responsible for parsing incoming network requests across multiple protocols, passing them through the strict 7-Layer Onion Pipeline, and routing them to the appropriate application Controllers.
|
|
5
|
+
|
|
6
|
+
## 2. Philosophy (Why does it exist?)
|
|
7
|
+
Many frameworks tightly couple their business logic to HTTP abstractions (like raw `request` objects). `ferrox-py`'s philosophy is to treat the transport layer as merely a delivery mechanism. Whether a command arrives via an HTTP REST call, a WebSocket message, or a GraphQL query, the underlying business logic remains completely isolated and agnostic to the network protocol.
|
|
8
|
+
|
|
9
|
+
## 3. Target Audience (Who is it for?)
|
|
10
|
+
This module is for developers building multi-protocol APIs. If your application needs to expose a traditional REST API for mobile clients, a GraphQL endpoint for internal frontends, and WebSockets for real-time notifications—all sharing the exact same business logic—this component manages that complexity safely.
|
|
11
|
+
|
|
12
|
+
## 4. Architecture (How does it work?)
|
|
13
|
+
- **Multi-Transport Architecture**: The application can run multiple servers (transports) simultaneously within the same asyncio event loop.
|
|
14
|
+
- **REST / API Gateway**: While agnostic, it strongly integrates with FastAPI as the default HTTP engine to leverage automatic OpenAPI schema generation and Pydantic type validation.
|
|
15
|
+
- **WebSockets / SSE**: Specialized routers handle real-time streaming and Server-Sent Events.
|
|
16
|
+
- **Decorators**: The component provides unified decorators (`@require_roles`, `@validate_schema`) that inject logic *before* the handler runs, regardless of the underlying transport.
|
|
17
|
+
- **Custom Transports**: Developers can implement the `ferrox_py.transports.base` interface to add entirely new triggers (e.g., raw TCP servers, message queue consumers, or file-system watchers).
|
|
18
|
+
|
|
19
|
+
## 5. Installation / Setup
|
|
20
|
+
To run the default HTTP REST gateway, FastAPI and an ASGI server (like Uvicorn) are required. GraphQL support requires additional libraries like Strawberry.
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install fastapi uvicorn pydantic
|
|
24
|
+
# Optional: pip install strawberry-graphql
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 6. Quickstart (Usage)
|
|
28
|
+
Defining a controller and applying decorators:
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from ferrox_py.web.decorators import require_roles, validate_schema
|
|
32
|
+
from pydantic import BaseModel
|
|
33
|
+
|
|
34
|
+
class UserPayload(BaseModel):
|
|
35
|
+
name: str
|
|
36
|
+
|
|
37
|
+
# These decorators hook into the Onion Pipeline automatically
|
|
38
|
+
@require_roles("admin")
|
|
39
|
+
@validate_schema(UserPayload)
|
|
40
|
+
async def create_user_handler(payload: UserPayload):
|
|
41
|
+
# At this point, the user is an admin and the payload is guaranteed valid
|
|
42
|
+
return {"message": f"User {payload.name} created successfully."}
|
|
43
|
+
|
|
44
|
+
# Custom utilities are also provided, e.g., parsing DataGrid queries:
|
|
45
|
+
from ferrox_py.transports.datagrid import parse_ag_grid_query
|
|
46
|
+
# query_opts = parse_ag_grid_query(request.url)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 7. Ecosystem Integration
|
|
50
|
+
The Web component is the entry point for external data and therefore integrates directly with the **Security** component (to evaluate headers and tokens), the **Pipes/Interceptors** (for validating schemas), and the **Observability** component (to extract and log Correlation IDs from incoming requests).
|