pyferro 0.5.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. pyferro-0.5.6/LICENSE +21 -0
  2. pyferro-0.5.6/PKG-INFO +651 -0
  3. pyferro-0.5.6/README.md +605 -0
  4. pyferro-0.5.6/pyferro/__init__.py +67 -0
  5. pyferro-0.5.6/pyferro/__main__.py +5 -0
  6. pyferro-0.5.6/pyferro/app.py +549 -0
  7. pyferro-0.5.6/pyferro/cli.py +164 -0
  8. pyferro-0.5.6/pyferro/compat.py +112 -0
  9. pyferro-0.5.6/pyferro/core/__init__.py +22 -0
  10. pyferro-0.5.6/pyferro/core/backplane.py +76 -0
  11. pyferro-0.5.6/pyferro/core/constants.py +20 -0
  12. pyferro-0.5.6/pyferro/core/http.py +118 -0
  13. pyferro-0.5.6/pyferro/core/lib/config.py +195 -0
  14. pyferro-0.5.6/pyferro/core/lifecycle.py +79 -0
  15. pyferro-0.5.6/pyferro/core/logger.py +177 -0
  16. pyferro-0.5.6/pyferro/core/router.py +18 -0
  17. pyferro-0.5.6/pyferro/core/security.py +155 -0
  18. pyferro-0.5.6/pyferro/core/session.py +532 -0
  19. pyferro-0.5.6/pyferro/core/tabular.py +121 -0
  20. pyferro-0.5.6/pyferro/plugins/__init__.py +26 -0
  21. pyferro-0.5.6/pyferro/plugins/auth/__init__.py +86 -0
  22. pyferro-0.5.6/pyferro/plugins/auth/config.py +46 -0
  23. pyferro-0.5.6/pyferro/plugins/auth/core.py +131 -0
  24. pyferro-0.5.6/pyferro/plugins/auth/discovery.py +152 -0
  25. pyferro-0.5.6/pyferro/plugins/auth/handlers.py +895 -0
  26. pyferro-0.5.6/pyferro/plugins/auth/models.py +510 -0
  27. pyferro-0.5.6/pyferro/plugins/auth/oauth.py +25 -0
  28. pyferro-0.5.6/pyferro/plugins/auth/permission_handlers.py +422 -0
  29. pyferro-0.5.6/pyferro/plugins/auth/permissions.py +65 -0
  30. pyferro-0.5.6/pyferro/plugins/auth/security.py +193 -0
  31. pyferro-0.5.6/pyferro/plugins/broadcast/__init__.py +182 -0
  32. pyferro-0.5.6/pyferro/plugins/crud/__init__.py +88 -0
  33. pyferro-0.5.6/pyferro/plugins/crud/admin_handlers.py +196 -0
  34. pyferro-0.5.6/pyferro/plugins/crud/auth.py +95 -0
  35. pyferro-0.5.6/pyferro/plugins/crud/coerce.py +126 -0
  36. pyferro-0.5.6/pyferro/plugins/crud/events.py +65 -0
  37. pyferro-0.5.6/pyferro/plugins/crud/handlers.py +825 -0
  38. pyferro-0.5.6/pyferro/plugins/crud/identity.py +241 -0
  39. pyferro-0.5.6/pyferro/plugins/crud/meta.py +279 -0
  40. pyferro-0.5.6/pyferro/plugins/crud/policy.py +140 -0
  41. pyferro-0.5.6/pyferro/plugins/crud/registry.py +89 -0
  42. pyferro-0.5.6/pyferro/plugins/crud/static/assets/index-BIwvZwye.js +2 -0
  43. pyferro-0.5.6/pyferro/plugins/crud/static/assets/index-BpxHDOGr.css +1 -0
  44. pyferro-0.5.6/pyferro/plugins/crud/static/index.html +13 -0
  45. pyferro-0.5.6/pyferro/plugins/crud/static_handler.py +135 -0
  46. pyferro-0.5.6/pyferro/plugins/db/__init__.py +22 -0
  47. pyferro-0.5.6/pyferro/plugins/db/session.py +161 -0
  48. pyferro-0.5.6/pyferro/plugins/files/__init__.py +36 -0
  49. pyferro-0.5.6/pyferro/plugins/files/handlers.py +162 -0
  50. pyferro-0.5.6/pyferro/plugins/files/models.py +62 -0
  51. pyferro-0.5.6/pyferro/plugins/files/service.py +195 -0
  52. pyferro-0.5.6/pyferro/plugins/files/upload.py +515 -0
  53. pyferro-0.5.6/pyferro/plugins/raw_ws/__init__.py +28 -0
  54. pyferro-0.5.6/pyferro/plugins/raw_ws/id_gen.py +26 -0
  55. pyferro-0.5.6/pyferro/plugins/raw_ws/manager.py +126 -0
  56. pyferro-0.5.6/pyferro/plugins/raw_ws/router.py +54 -0
  57. pyferro-0.5.6/pyferro/plugins/raw_ws/session.py +136 -0
  58. pyferro-0.5.6/pyferro/plugins/seo/__init__.py +72 -0
  59. pyferro-0.5.6/pyferro/plugins/seo/config.py +178 -0
  60. pyferro-0.5.6/pyferro/plugins/seo/detector.py +103 -0
  61. pyferro-0.5.6/pyferro/plugins/seo/indexnow.py +294 -0
  62. pyferro-0.5.6/pyferro/plugins/seo/renderer.py +259 -0
  63. pyferro-0.5.6/pyferro/plugins/seo/router.py +189 -0
  64. pyferro-0.5.6/pyferro/plugins/seo/schemas.py +34 -0
  65. pyferro-0.5.6/pyferro/plugins/seo/sitemap.py +303 -0
  66. pyferro-0.5.6/pyferro/plugins/smart_cache/__init__.py +24 -0
  67. pyferro-0.5.6/pyferro/plugins/smart_cache/engine.py +353 -0
  68. pyferro-0.5.6/pyferro/plugins/smart_cache/handlers.py +54 -0
  69. pyferro-0.5.6/pyferro.egg-info/PKG-INFO +651 -0
  70. pyferro-0.5.6/pyferro.egg-info/SOURCES.txt +73 -0
  71. pyferro-0.5.6/pyferro.egg-info/dependency_links.txt +1 -0
  72. pyferro-0.5.6/pyferro.egg-info/requires.txt +27 -0
  73. pyferro-0.5.6/pyferro.egg-info/top_level.txt +1 -0
  74. pyferro-0.5.6/pyproject.toml +79 -0
  75. pyferro-0.5.6/setup.cfg +4 -0
pyferro-0.5.6/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alex Titoff and rsgi-wsrpc contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
pyferro-0.5.6/PKG-INFO ADDED
@@ -0,0 +1,651 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyferro
3
+ Version: 0.5.6
4
+ Summary: High-performance reactive fullstack Python framework on Rust RSGI (Granian) with symmetric WSRPC (JSON-RPC 2.0) and Tabular Data Compression.
5
+ Author-email: Alex Titoff <a.tit.off@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/atitoff-dotcom/pyferro
8
+ Project-URL: Documentation, https://github.com/atitoff-dotcom/pyferro/blob/main/docs/readme.md
9
+ Project-URL: Repository, https://github.com/atitoff-dotcom/pyferro.git
10
+ Keywords: pyferro,rsgi,granian,wsrpc,json-rpc,websocket,reactive,fastapi-alternative,django-alternative
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Framework :: AsyncIO
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Internet :: WWW/HTTP
19
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: granian>=1.6.0
24
+ Requires-Dist: orjson>=3.9.0
25
+ Requires-Dist: pyjwt>=2.8.0
26
+ Requires-Dist: cryptography>=42.0.0
27
+ Provides-Extra: db
28
+ Requires-Dist: sqlalchemy[asyncio]>=2.0.0; extra == "db"
29
+ Requires-Dist: greenlet>=3.0.0; extra == "db"
30
+ Provides-Extra: sqlite
31
+ Requires-Dist: sqlalchemy[asyncio]>=2.0.0; extra == "sqlite"
32
+ Requires-Dist: aiosqlite>=0.19.0; extra == "sqlite"
33
+ Requires-Dist: greenlet>=3.0.0; extra == "sqlite"
34
+ Provides-Extra: postgres
35
+ Requires-Dist: sqlalchemy[asyncio]>=2.0.0; extra == "postgres"
36
+ Requires-Dist: asyncpg>=0.29.0; extra == "postgres"
37
+ Provides-Extra: mysql
38
+ Requires-Dist: sqlalchemy[asyncio]>=2.0.0; extra == "mysql"
39
+ Requires-Dist: asyncmy>=0.2.9; extra == "mysql"
40
+ Provides-Extra: full
41
+ Requires-Dist: sqlalchemy[asyncio]>=2.0.0; extra == "full"
42
+ Requires-Dist: aiosqlite>=0.19.0; extra == "full"
43
+ Requires-Dist: asyncpg>=0.29.0; extra == "full"
44
+ Requires-Dist: asyncmy>=0.2.9; extra == "full"
45
+ Dynamic: license-file
46
+
47
+ # PyFerro: Reactive Full-Featured Python Framework
48
+
49
+ > **"Everything Django should have been, and everything FastAPI forgot."**
50
+ > High-performance asynchronous web framework built on **Rust (Granian RSGI)** with bidirectional **WSRPC (JSON-RPC 2.0)**, built-in async database ORM, modern authentication, and transactional two-phase file uploading.
51
+
52
+ ---
53
+
54
+ ## 🧭 Table of Contents
55
+ 1. [Core Philosophy & Manifesto](#-core-philosophy--manifesto)
56
+ 2. [Architecture: Core + Plugins + Application](#-architecture-core--plugins--application)
57
+ * [Architecture for Beginners with Diagrams (docs/architecture_for_beginners.md)](docs/architecture_for_beginners.md)
58
+ * [Recommended Project Structure (Directory Tree)](#-recommended-project-structure-directory-tree)
59
+ 3. [Comparison: PyFerro vs Django vs FastAPI](#-comparison-PyFerro-vs-django-vs-fastapi)
60
+ 4. [🤖 AI-Native: Token-Efficient & Purpose-Built for LLMs](#-ai-native-token-efficient--purpose-built-for-llms)
61
+ 5. [Quickstart in 60 Seconds](#-quickstart-in-60-seconds)
62
+ 6. [Core Network Engine](#-core-network-engine)
63
+ * [Complete Core Developer Guide (docs/core.md)](docs/core.md)
64
+ 7. [Official System Plugins](#-official-system-plugins)
65
+ * [Database Plugin (db)](#1-database-plugin-pluginsdb)
66
+ * [Authentication & User Plugin (auth)](#2-authentication--user-plugin-pluginsauth)
67
+ * [Two-Phase File Upload Plugin (files)](#3-two-phase-file-upload-plugin-pluginsfiles)
68
+ * [Smart Event-Driven Cache Plugin (smart_cache)](#4-smart-event-driven-cache-plugin-pluginssmart_cache)
69
+ * [Modular Backend Test Framework (tests/)](#5-modular-backend-test-framework-tests)
70
+ * [🛡️ Security Whitepaper & Benchmarks (SECURITY_AND_PERFORMANCE.md)](SECURITY_AND_PERFORMANCE.md)
71
+ 8. [Creating Custom Plugins & Modules in the app Directory](#-creating-custom-plugins--modules-in-the-app-directory)
72
+
73
+ 9. [Client Library (TypeScript/JavaScript)](#-client-library-typescriptjavascript)
74
+ 10. [🌟 What's New in v0.3.3](#-whats-new-in-v033)
75
+ 11. [License](#-license)
76
+
77
+ ---
78
+
79
+ ## 💡 Core Philosophy & Manifesto
80
+
81
+ The modern web has changed: users no longer tolerate static web pages reloading for hundreds of milliseconds. Users expect instant interactions (1–5 ms), reactive real-time state synchronization, and live progress streaming.
82
+
83
+ Yet Python developers were forced to choose between two extremes:
84
+ 1. **Django** — a 20-year-old monolithic design from the Web 2.0 era. Adding websockets and reactivity requires bundling `Django + DRF + Channels + Redis + Celery + Daphne`, consuming hundreds of megabytes of RAM per worker.
85
+ 2. **FastAPI** — performant, but trapped in the flat HTTP/1.1 REST paradigm (Request-Response). Every user action opens a new TCP connection, exchanges kilobytes of redundant HTTP headers, and lacks built-in batteries (auth, sessions, file transactions) — forcing developers to stitch together 50 disparate third-party libraries.
86
+
87
+ **`PyFerro` combines the best of both worlds:**
88
+ * **From Rust and Granian** — blistering RSGI runtime performance without Python GIL overhead.
89
+ * **From WSRPC (JSON-RPC 2.0)** — a single persistent, multiplexed channel for all operations, symmetric RPC invocation (server can call client), and native multi-return streaming.
90
+ * **From Django** — production-grade batteries (Auth, DB, Two-Phase File uploads) delivered as decoupled, lightweight plugins.
91
+
92
+ ---
93
+
94
+ ## 🏛 Architecture: Core + Plugins + Application
95
+
96
+ The architecture enforces a strict unidirectional dependency hierarchy (Clean Architecture):
97
+
98
+ ```text
99
+ ┌─────────────────────────────────────────────────────────────────────────┐
100
+ │ 1. YOUR APPLICATION (Application) │
101
+ │ │
102
+ │ Knows about all components: configures application in code (Code-First),
103
+ │ activates necessary system plugins, and executes domain business logic
104
+ │ Examples: Social Network, CRM, Forum, Customer Portal, IoT Server. │
105
+ └────────────────────────────────────┬────────────────────────────────────┘
106
+ │ consumes and aggregates
107
+ ┌────────────────────────────────────▼────────────────────────────────────┐
108
+ │ 2. SYSTEM & APPLICATION PLUGINS │
109
+ │ │
110
+ │ [ Plugin: DB ] [ Plugin: Auth ] [ Plugin: Files ] │
111
+ │ Async SQLAlchemy 2.0 Users, JWT, 2PC file streaming, │
112
+ │ SQLite / PostgreSQL roles and permissions registry & Nginx offload │
113
+ │ │
114
+ │ [ Plugin: CRUD ] [ Plugin: SEO ] [ Plugin: Smart Cache ] │
115
+ │ Reactive CRUD, RLS, Dynamic Rendering, Reactive event-driven │
116
+ │ Svelte 5 SPA Admin Search engine crawlers feedback cache (0 ms) │
117
+ │ │
118
+ │ [ Domain Plugins: Forum, Billing, Notifications, Analytics... ] │
119
+ └────────────────────────────────────┬────────────────────────────────────┘
120
+ │ registers into
121
+ ┌────────────────────────────────────▼────────────────────────────────────┐
122
+ │ 3. NETWORK CORE (Core) │
123
+ │ │
124
+ │ Pure high-performance socket and RSGI runtime (Granian in Rust). │
125
+ │ ZERO knowledge of databases or application domain models. │
126
+ │ Responsible for: WSRPC (JSON-RPC 2.0), multi-return, sessions, 2PC. │
127
+ └─────────────────────────────────────────────────────────────────────────┘
128
+ ```
129
+
130
+ ### Core Architectural Rules:
131
+ 1. **The Core is Autonomous**: `core/` contains zero imports from application domains or database models.
132
+ 2. **Plugins are Modular**: Each plugin tackles one concern and registers its handlers via core APIs (`@rpc_method`, `@on_startup`, `session.register_on_close`).
133
+ 3. **Application Governs Composition**: Need a lightweight microservice without a database? Simply omit the `db` plugin. Need a full-stack portal? Import the complete battery bundle.
134
+
135
+ ---
136
+
137
+ ### 📁 Recommended Project Structure (Directory Tree)
138
+
139
+ Below is the production-tested repository layout, clearly demarcating the network engine (`core/`), official batteries (`app/system/`), and custom application modules (`app/<modules>/`):
140
+
141
+ ```text
142
+ my_project/
143
+ ├── core/ # ⚡ NETWORK CORE (RSGI + WSRPC)
144
+ │ ├── lib/
145
+ │ │ └── config.py # Code-First configuration & configure()
146
+ │ ├── constants.py # System constants (ADMIN_ROLE, DEFAULT_USER_ROLE)
147
+ │ ├── lifecycle.py # Async hooks @on_startup and @on_shutdown
148
+ │ ├── logger.py # High-performance structured logging
149
+ │ ├── router.py # HTTP routing on top of RSGI (@http_route)
150
+ │ ├── security.py # Argon2id, JWT tokens, RSA cryptography
151
+ │ ├── session.py # JsonRpcSession, @rpc_method, ContextVars, Rate-Limiter
152
+ │ └── tabular.py # Deterministic tabular payload compression (RFC 0002, pack_tabular)
153
+ │
154
+ ├── app/ # 📦 APPLICATION & PLUGIN LAYER
155
+ │ ├── system/ # 🔌 System Plugins (Official Batteries)
156
+ │ │ ├── db.py # Async SQLAlchemy 2.0 engine (async_session, Base)
157
+ │ │ ├── broadcast.py # Event broadcaster across active sockets
158
+ │ │ ├── auth/ # Users, scopes, and Row-Level Security (RLS)
159
+ │ │ │ ├── models.py # Models: User, Role, Permit
160
+ │ │ │ ├── handlers.py # RPC methods: auth.*
161
+ │ │ │ ├── permissions.py # Scope and role verification logic
162
+ │ │ │ └── security.py # Hashing & authorization rules
163
+ │ │ ├── login/ # Authentication, RSA handshake, RefreshToken
164
+ │ │ │ ├── handlers.py # RPC methods: login.submit, login.refresh, login.whoami
165
+ │ │ │ └── db.py # Active sessions and token persistence
166
+ │ │ ├── files/ # File metadata registry & storage service
167
+ │ │ │ ├── models.py # FileMetadata ORM model
168
+ │ │ │ ├── service.py # FileStorageService (quota, schema migration, deletion)
169
+ │ │ │ └── handlers.py # HTTP route /upload and RPC methods: files.*
170
+ │ │ ├── admin/ # Administration control plane (sessions, cache, users)
171
+ │ │ │ └── handlers.py
172
+ │ │ └── internal_api/ # Interactive RPC documentation generator
173
+ │ │ ├── api.html # Built-in UI sandbox
174
+ │ │ ├── handlers.py # API inspection endpoints
175
+ │ │ └── generate_docs.py # Docstring and signature parser
176
+ │ │
177
+ │ └── <business_modules>/ # 🚀 Your application business domains
178
+ │ ├── forum/ # Example: Community discussion module
179
+ │ │ ├── models.py # Topic, Message, Tag models
180
+ │ │ └── handlers.py # RPC methods: forum.get_topics, forum.create_topic
181
+ │ ├── billing/ # Example: Billing and invoicing module
182
+ │ │ ├── models.py # Invoice, Transaction models
183
+ │ │ └── handlers.py # RPC methods: billing.create_invoice, billing.pay
184
+ │ └── notifications/ # Example: Real-time notification service
185
+ │ └── handlers.py # Push dispatching via broadcast
186
+ │
187
+ ├── client/ # 💻 CLIENT LIBRARIES
188
+ │ └── wsrpc.ts # Official TypeScript/JavaScript WSRPC client
189
+ │
190
+ ├── docs/ # 📚 Framework Documentation (EN)
191
+ │ ├── readme.md
192
+ │ ├── core.md # Comprehensive Core developer guide
193
+ │ └── files.md # Two-phase file upload guide (2PC)
194
+ │
195
+ ├── docs_ru/ # 📚 Framework Documentation (RU Twin)
196
+ │ ├── readme.md
197
+ │ ├── core.md # Comprehensive Core developer guide
198
+ │ └── files.md # Two-phase file upload guide (2PC)
199
+ │
200
+ ├── main.py # 🚀 Entrypoint: plugin composition, RSGI application
201
+ └── pyproject.toml # 📦 Dependencies and package manifest
202
+ ```
203
+
204
+ ---
205
+
206
+ ## ⚡ Comparison: PyFerro vs Django vs FastAPI
207
+
208
+ ### 1. Client-Server Interaction Model
209
+
210
+ #### Traditional REST (FastAPI / Django):
211
+ Every operation re-initiates a TCP/TLS handshake, transfers cookies/headers, and terminates:
212
+ ```text
213
+ [ Client ] ──── TCP + TLS Handshake (50-100 ms) ────► [ Server ]
214
+ [ Client ] ──── POST /api/items (Headers + Body) ───► [ Server ]
215
+ [ Client ] ◄─── 200 OK (Headers + Body) ──────────── [ Server ] (connection closed)
216
+
217
+ [ Client ] ──── TCP + TLS Handshake (50-100 ms) ────► [ Server ]
218
+ [ Client ] ──── GET /api/user/profile ──────────────► [ Server ]
219
+ [ Client ] ◄─── 200 OK ───────────────────────────── [ Server ]
220
+ ```
221
+
222
+ #### Reactive WSRPC (`PyFerro`):
223
+ A single persistent, multiplexed WebSocket channel. Zero handshake latency, instant 1–3 ms roundtrips:
224
+ ```text
225
+ [ Client ] ═════════════════════════════════════════► [ Server ]
226
+ (Persistent secure WSRPC socket)
227
+
228
+ ─── id: 1, method: "items.create" ───────► (1 ms)
229
+ ◄── id: 1, result: { id: 42 } ──────────── (1 ms)
230
+
231
+ ─── id: 2, method: "user.get_profile" ───► (1 ms)
232
+ ◄── id: 2, result: { name: "Alex" } ────── (1 ms)
233
+
234
+ ◄── SERVER PUSH: method: "notify" ──────── (Server initiates RPC on client!)
235
+ ```
236
+
237
+ ### 2. Feature Matrix
238
+
239
+ | Feature | Django | FastAPI | `PyFerro` |
240
+ | :--- | :--- | :--- | :--- |
241
+ | **Network Engine** | Python WSGI / slow ASGI | Uvicorn (ASGI) | **Granian (Rust RSGI)** 🚀 |
242
+ | **Response Latency** | 80–250 ms | 30–120 ms | **1–5 ms** |
243
+ | **Symmetry** | ❌ Client ➔ Server only | ❌ Client ➔ Server only | ✅ **Client ⇄ Server (Bidirectional)** |
244
+ | **Progress Streaming** | ❌ Requires Redis + Channels | ❌ Heavy websocket boilerplate | ✅ **Native multi-return (`stream: true`)** |
245
+ | **RAM Footprint** | ~150–250 MB per worker | ~80–120 MB per worker | **~25–40 MB per worker** |
246
+ | **File Transfers** | Buffered in worker RAM | Buffered in RAM / SpooledFile | **Streaming O(1) RAM + 2PC + Nginx Offload** |
247
+ | **Built-in Auth** | ✅ Included (Synchronous) | ❌ None (Roll your own) | ✅ **Included (JWT + Refresh + Argon2)** |
248
+ | **Infrastructure** | Python + Postgres + Redis + Celery | Python + Postgres + ... | **Single Granian binary + SQLite/Postgres** |
249
+ | **AI-Native Engineering** | ❌ Highly Inefficient | ⚠️ Moderate (heavy boilerplate) | 🚀 **Maximum (AI-Native Architecture)** |
250
+ | **LLM Token Consumption** | ~3,000 – 5,000 tokens / feature | ~2,000 – 3,500 tokens / feature | **~300 – 600 tokens (5–10x savings!)** |
251
+ | **Files Touched per Feature** | 5–7 files | 4–6 files | **1–2 files (`handlers.py` + `rpc.call`)** |
252
+ | **Code Boilerplate** | Extreme (DTOs, URLs, views, redux) | High (Pydantic schemas, Depends) | **Minimal (clean `@rpc_method`)** |
253
+
254
+ ### 3. Server CPU Processing Time per Operation
255
+
256
+ Why is `PyFerro` **20–30x more CPU-efficient** than Django (DRF / Channels)?
257
+
258
+ | Processing Phase | Django (DRF / Channels) | PyFerro (Rust + WSRPC) | Efficiency Gain |
259
+ | :--- | :--- | :--- | :--- |
260
+ | **Network & Frame Intake** | **1,500 – 3,000 µs** (TCP/TLS cycle, ASGI bridge, Python HTTP header parsing) | **50 – 80 µs** (Persistent socket, Rust Tokio/Hyper zero-copy frame reader) | **~30x faster** |
261
+ | **Auth & Session Lookup** | **2,000 – 4,000 µs** (Re-parse cookies, DB/cache user query, CSRF checks on every request) | **10 – 20 µs** (Session cached in socket memory, zero redundant queries) | **~150x faster** |
262
+ | **Routing & Middleware** | **800 – 1,500 µs** (7–10 Python middlewares, Regex URL routing) | **15 – 30 µs** (O(1) hash table lookup `RPC_REGISTRY[method]`) | **~50x faster** |
263
+ | **Parsing & Dispatch** | **1,500 – 3,500 µs** (Heavy DRF serializers, field instantiation) | **80 – 150 µs** (Async kwargs auto-unpacking directly to handler) | **~20x faster** |
264
+ | **Response Serialization** | **1,500 – 3,000 µs** (DRF JSON render, HTTP headers, middleware return) | **100 – 200 µs** (JSON-RPC 2.0 or RFC 0002 Tabular zero-overhead framing) | **~15x faster** |
265
+ | **TOTAL Server CPU Time:** | **7,000 – 15,000 µs (7–15 ms)** | **300 – 500 µs (0.3–0.5 ms)** | 🚀 **20–30x less CPU time!** |
266
+
267
+ > **Key takeaway:** Django suffers from "stateless amnesia" — re-authenticating and parsing HTTP on every click. `PyFerro` stays persistent and warm, routing RPCs directly to Python functions without HTTP bureaucracy.
268
+
269
+ ---
270
+
271
+ ## 🤖 AI-Native: Token-Efficient & Purpose-Built for LLMs
272
+
273
+ `PyFerro` is engineered from the ground up for modern AI-assisted engineering: **code authored, reviewed, and refactored by LLMs and Autonomous AI Agents (Claude, Cursor, Gemini, GPT-4o, GitHub Copilot)**.
274
+
275
+ In conventional frameworks (FastAPI / Django), up to 80% of generated tokens are squandered on glue code, serialization boilerplate, and redundant plumbing. In `PyFerro`, the unified contract yields **massive savings on LLM context windows and developer token budgets**.
276
+
277
+ ```text
278
+ TOKEN CONSUMPTION FOR IMPLEMENTING A FEATURE (E.G. ADD COMMENT WITH REAL-TIME PUSH)
279
+
280
+ Django REST: ████████████████████████████████████████ (~4,200 tokens)
281
+ FastAPI: █████████████████████████ (~2,600 tokens)
282
+ PyFerro: ███ (~350 tokens) ──► UP TO 85% TOKEN REDUCTION!
283
+ ```
284
+
285
+ ### Why AI Writes `PyFerro` Code Faster, More Accurately, and Cheaper:
286
+
287
+ #### 1. Zero-Boilerplate Simplicity
288
+ You no longer need to burn context asking models to generate Pydantic request DTOs, response DTOs, HTTP error handlers, route registration boilerplate, and mirrored frontend `fetch()` wrappers.
289
+ * **Backend**: One decorator `@rpc_method("domain.action")`. User (`current_user_ctx`) and session context are accessible natively without intricate `Depends()` dependency graphs.
290
+ * **Frontend**: One line: `await rpc.call("domain.action", { ... })`.
291
+
292
+ #### 2. Unified Protocol vs Stack Sprawl
293
+ In traditional systems, developers must explain multiple disparate transport layers to the AI: REST for CRUD, WebSockets/SSE for notifications, Redis Pub/Sub for worker tasks, and Multipart for file uploads. Models exhaust their attention budgets and hallucinate.
294
+ With `PyFerro`, **all communication adheres to one symmetrical protocol WSRPC (JSON-RPC 2.0)**: queries, mutations, progress streams (`stream: true`), server push notifications (`rpc.on`), and interactive server-to-client dialogs (`rpc.registerMethod`).
295
+
296
+ #### 3. High Context Locality
297
+ Modules in `app/<module>/` are strictly decoupled. When assigning an AI agent a feature or bug fix, you only need to provide **1 single file** (`handlers.py`), rather than sprawling architectural files.
298
+ * **Fewer Input Tokens**: Instant, near-zero latency generation from AI agents.
299
+ * **Higher Precision**: Eliminates hallucinations caused by oversized, noisy context windows.
300
+ * **Direct Cost Reduction**: Lowers operational API billing on commercial models.
301
+
302
+ #### 4. Built-in AI Guide (`AGENTS.md`)
303
+ The repository root includes a dedicated instruction file [AGENTS.md](AGENTS.md) tailored for AI coding assistants (Cursor, Antigravity, Claude Code, Windsurf, ChatGPT). It codifies framework architecture, `@rpc_method` contracts, keyword argument auto-mapping, Tabular compression (RFC 0002), and anti-hallucination guardrails. This document is updated with every release.
304
+
305
+ ---
306
+
307
+ ## 🚀 Installation & Quickstart
308
+
309
+ ### 📦 Installation via PIP
310
+
311
+ Install the minimal core (Granian RSGI, Orjson, WSRPC, Cryptography):
312
+ ```bash
313
+ pip install PyFerro
314
+ ```
315
+
316
+ Or install with database support and drivers depending on your target stack:
317
+ ```bash
318
+ pip install "PyFerro[sqlite]" # Async SQLite (aiosqlite + SQLAlchemy 2.0)
319
+ pip install "PyFerro[postgres]" # Async PostgreSQL (asyncpg + SQLAlchemy 2.0)
320
+ pip install "PyFerro[mysql]" # Async MySQL (asyncmy + SQLAlchemy 2.0)
321
+ pip install "PyFerro[full]" # All drivers and plugins included
322
+ ```
323
+
324
+ ---
325
+
326
+ ### ⚡ Option A: Interactive Showcase Demo (1-Click)
327
+
328
+ The repository includes a ready-to-run interactive showcase (`examples/showcase/`):
329
+
330
+ ```bash
331
+ # Linux / macOS:
332
+ ./examples/showcase/run.sh
333
+
334
+ # macOS (without terminal):
335
+ # Double-click examples/showcase/run_mac.command directly in Finder!
336
+
337
+ # Windows (cmd):
338
+ examples\showcase\run.bat
339
+
340
+ # Windows (PowerShell):
341
+ .\examples\showcase\run.ps1
342
+ ```
343
+ The launcher automatically provisions a `.venv`, installs dependencies, and boots the Granian server. Open `http://127.0.0.1:8080` in your browser to inspect real-time WSRPC operations, the reactive database, Tabular payload compression, and streaming progress.
344
+
345
+ ---
346
+
347
+ ### 🛠 Option B: Minimal Server (`main.py`)
348
+ ```python
349
+ import os
350
+ from pyferro import FerroApp, rpc_method, tabular_response, RPCError
351
+
352
+ # 1. Code-First application entrypoint
353
+ app = FerroApp(
354
+ secret_key=os.getenv("SECRET_KEY", "dev-secret-key-change-in-production"),
355
+ database_url=os.getenv("DATABASE_URL", "sqlite+aiosqlite:///app.db"),
356
+ static_dir="./public", # Zero-Copy static files via Rust RSGI
357
+ index_file="index.html", # Auto-served on GET /
358
+ cors=True
359
+ )
360
+
361
+ # 2. Public RPC method with auto-unpacked kwargs
362
+ @app.rpc("math.add", public=True)
363
+ async def add_numbers(a: int = 0, b: int = 0):
364
+ return {"result": a + b}
365
+
366
+ # 3. Multi-return streaming progress method
367
+ @app.rpc("task.run_long")
368
+ async def run_task(session, rpc_id: int = 0):
369
+ for step in range(1, 4):
370
+ # Transmit intermediate progress chunk to the socket
371
+ await session.send_stream_chunk(rpc_id, {"progress": step * 33})
372
+ return {"status": "completed"}
373
+
374
+ # 4. Run server (or via granian CLI)
375
+ if __name__ == "__main__":
376
+ app.run(host="127.0.0.1", port=8080, workers=1)
377
+ ```
378
+
379
+ ### 2. Launch Server
380
+ Via Python:
381
+ ```bash
382
+ python main.py
383
+ ```
384
+ Or directly using Granian CLI (recommended for production):
385
+ ```bash
386
+ granian --rsgi main:app --host 127.0.0.1 --port 8080 --workers 1
387
+ ```
388
+
389
+ ### 3. Invoke from Client (JavaScript / TypeScript)
390
+ ```javascript
391
+ import { BinaryWSRPC } from './wsrpc.js';
392
+
393
+ const client = new BinaryWSRPC('ws://127.0.0.1:8080');
394
+ await client.connect();
395
+
396
+ // Regular RPC call
397
+ const sum = await client.call('math.add', { a: 10, b: 25 });
398
+ console.log(sum.result); // 35
399
+
400
+ // Multi-return streaming call
401
+ await client.callStream('task.run_long', {}, (chunk) => {
402
+ console.log(`Progress: ${chunk.progress}%`);
403
+ });
404
+ ```
405
+
406
+ ---
407
+
408
+ ## ⚙️ Core Network Engine
409
+
410
+ > 📖 **For the complete technical manual with code examples, see: [docs/core.md](docs/core.md)**.
411
+
412
+ The network core resides in the `core/` directory and exposes the following building blocks:
413
+
414
+ * **[core/session.py](core/session.py)**:
415
+ * `JsonRpcSession`: Manages persistent client sockets.
416
+ * Multiplexes incoming and outgoing RPC requests by numeric `id`.
417
+ * Built-in **Rate-Limiter (Token Bucket)** for protection against flooding (30 req/s) with zero runtime overhead.
418
+ * Isolated Python `ContextVar` instances (`current_user_ctx`, `current_session_ctx`, `current_rpc_id_ctx`, `current_transport_ctx`), accessible anywhere in the async execution context.
419
+ * Session termination hooks: `session.register_on_close(callback)` for clean resource teardown.
420
+ * Symmetric client invocation from server: `await session.send_request("client_method", params)`.
421
+
422
+ * **[core/router.py](core/router.py)**:
423
+ * `@http_route(path, methods)` decorator to register raw RSGI HTTP handlers.
424
+ * High-throughput file streams, webhooks, and health checks.
425
+
426
+ * **[core/tabular.py](docs/tabular_compression.md)**:
427
+ * Deterministic tabular payload compression (RFC 0002, `pack_tabular`, `@tabular_response`).
428
+ * Cuts 50–70% of network traffic by transmitting property schemas once and packing records into a 2D matrix.
429
+ * Direct SQL tuple optimization bypasses dictionary allocations, minimizing Python GC overhead.
430
+
431
+ * **[core/security.py](core/security.py)**:
432
+ * Password hashing using **Argon2id**.
433
+ * JWT access token issuance and validation.
434
+ * Asymmetric RSA encryption for secure credential exchange.
435
+
436
+ * **[core/lifecycle.py](core/lifecycle.py)**:
437
+ * Application startup dispatcher `@on_startup` (runs migrations, cache warming, and background daemons before opening sockets).
438
+
439
+ * **[core/lib/config.py](core/lib/config.py)**:
440
+ * Settings parser for `settings.yaml` supporting environment variable overrides.
441
+
442
+ ---
443
+
444
+ ## 🔌 Official System Plugins
445
+
446
+ The framework includes pre-built and tested system batteries in `app/system/`:
447
+
448
+ ### 1. Database Plugin (`plugins/db`)
449
+ * **Stack**: Async SQLAlchemy 2.0 + `orjson` for ultra-fast JSON serialization.
450
+ * **Engines**: SQLite out-of-the-box (zero configuration). Seamless switch to PostgreSQL via `settings.yaml`.
451
+ * **Usage**:
452
+ ```python
453
+ from app.system.db import async_session, Base
454
+ from sqlalchemy import select
455
+
456
+ async with async_session() as db:
457
+ users = (await db.execute(select(User))).scalars().all()
458
+ ```
459
+
460
+ ---
461
+
462
+ ### 2. Authentication & User Plugin (`plugins/auth`)
463
+ * **Features**:
464
+ * `User` model, database-driven role architecture (dynamic roles in `auth_role`, `auth_rpc_permission`, superadmin bypass).
465
+ * **Row-Level Security (RLS)**: base classes `BasicSecureModel` and `RowSecureModel` for tenant/owner scoping.
466
+ * Reliable session extension via `RefreshToken` and multi-device tracking in `ActiveSession`.
467
+ * Context-based user retrieval anywhere without passing parameters:
468
+ ```python
469
+ from core.session import current_user_ctx
470
+ user = current_user_ctx.get()
471
+ ```
472
+
473
+ ---
474
+
475
+ ### 3. Two-Phase File Upload Plugin (`plugins/files`)
476
+ * Comprehensive architecture: see **[docs/files.md](docs/files.md)**.
477
+ * **Two-Phase Commit Workflow**:
478
+ 1. Client initiates upload transaction: server provisions isolated `/tmp/app_uploads/<folder_hash>/`.
479
+ 2. Client streams files via `POST /upload`. Bytes stream directly to disk without memory buffering.
480
+ 3. If client disconnects — core triggers `session.on_close` and erases the temp folder immediately.
481
+ 4. On completion — folder moves atomically to production storage `/files/<folder_hash>/` in 0 milliseconds.
482
+ 5. Files are indexed in unified `file_metadata` database table (quotas, original names, MIME types).
483
+ 6. Downloads are served directly by **Nginx** with zero Python overhead.
484
+
485
+ ---
486
+
487
+ ### 4. Smart Reactive Cache Plugin (`plugins/smart_cache`)
488
+ * Comprehensive architecture: see **[docs/smart_cache.md](docs/smart_cache.md)** and **[RFC 0001](rfc/0001-smart-cache.md)**.
489
+ * **0 ms Latency Principle & Push Invalidation**:
490
+ * Instant screen rendering from L1 RAM (or L2 IndexedDB/localStorage) with zero network wait.
491
+ * Server automatically tracks mutations and pushes `cache.invalidate` impulses or targeted `cache.patch` via `@invalidates(tags=...)`.
492
+ * Zero blind polling — the WebSocket stays completely silent until data actually changes.
493
+ * Version handshake (`cache.sync_check`) on reconnect syncs only tags that changed during offline state.
494
+
495
+ ---
496
+
497
+ ### 5. Modular Backend Test Framework (`tests/`)
498
+ * Comprehensive guide: see **[docs/testing.md](docs/testing.md)**.
499
+ * **Client-Perspective Black-Box Testing**:
500
+ * Validates the backend exactly as a real frontend client interacts with it (over WebSocket WSRPC and HTTP).
501
+ * `PersonaManager`: pre-authenticated sessions (`admin`, `user`, `guest`) with automatic local database seeding and RLS bypass.
502
+ * Native verification of streaming (`stream: true`), push notification interception (`cache.invalidate`, `cache.patch`), and two-phase uploads.
503
+ * Built-in stress & load testing (`tests/suites/test_load.py`): benchmarks RPS, latency percentiles (p50/p95/p99), and broadcast fan-out reliability.
504
+
505
+ ---
506
+
507
+ ### 6. Industrial Reliability, Security Audit & High-Load Benchmarks
508
+ * Full Security Whitepaper: see **[SECURITY_AND_PERFORMANCE.md](SECURITY_AND_PERFORMANCE.md)**.
509
+ * Complete Testing & Benchmarking Manual: see **[docs/testing.md](docs/testing.md)**.
510
+ * **Autonomous External Security Auditor (`scripts/security_audit.py`)**:
511
+ * Automated black-box penetration tester covering **9 critical attack vectors**: Zero-Leakage 404, Header Leakage, CSWSH, 12MB DoS Bombs, JSON-RPC Compliance, Prototype Pollution, RBAC Privilege Isolation, CRUD RLS, and `alg:none` JWT Forgery.
512
+ ```bash
513
+ # Run 9/9 pentest suite (auto-detects port 8080 or 8000)
514
+ python scripts/security_audit.py --target http://127.0.0.1:8080
515
+ ```
516
+ * **High-Throughput Open Stress Benchmark (`scripts/benchmark.py`)**:
517
+ * Standalone tool with real-time ASCII progress bar, measuring true WebSocket throughput (>11,000 RPS single-worker), sub-millisecond latencies (p50: 0.9–1.6 ms), and wire bandwidth.
518
+ * Honors kernel Token-Bucket DoS rate limiting (30 req/sec per socket).
519
+ ```bash
520
+ # Run stress test (500 concurrent sockets, 12,500 requests)
521
+ python scripts/benchmark.py --target http://127.0.0.1:8080 --concurrency 500 --requests 12500
522
+ ```
523
+
524
+ ---
525
+
526
+ ## 🛠 Creating Custom Plugins & Modules in the app Directory
527
+
528
+
529
+ Creating a custom feature module (e.g. support ticket system `app/tickets/`) is straightforward:
530
+
531
+ ```python
532
+ # app/tickets/handlers.py
533
+ from core.session import rpc_method, RPCError, current_user_ctx
534
+ from app.system.db import async_session
535
+ from app.system.files.service import FileStorageService
536
+
537
+ @rpc_method("tickets.create")
538
+ async def create_ticket(session, params):
539
+ user = current_user_ctx.get()
540
+ if not user:
541
+ raise RPCError("Authentication required")
542
+
543
+ title = params.get("title")
544
+ text = params.get("text")
545
+ folder_hash = params.get("folder_hash") # If files were attached
546
+
547
+ # Persist ticket in database
548
+ async with async_session() as db:
549
+ async with db.begin():
550
+ ticket = Ticket(title=title, text=text, author_id=user.id, folder=folder_hash)
551
+ db.add(ticket)
552
+
553
+ return {"status": "ok", "ticket_id": ticket.id}
554
+
555
+ @rpc_method("tickets.delete")
556
+ async def delete_ticket(session, params):
557
+ ticket_id = params.get("ticket_id")
558
+
559
+ async with async_session() as db:
560
+ ticket = await db.get(Ticket, ticket_id)
561
+ if ticket and ticket.folder:
562
+ # Atomically delete all bundled files from disk and registry
563
+ await FileStorageService.delete_bundle(ticket.folder)
564
+ await db.delete(ticket)
565
+ await db.commit()
566
+
567
+ return {"deleted": True}
568
+ ```
569
+
570
+ To enable the module, import its handlers in `main.py`:
571
+ ```python
572
+ # main.py
573
+ import app.tickets.handlers # noqa: F401
574
+ ```
575
+
576
+ ---
577
+
578
+ ## 💻 Client Library (TypeScript/JavaScript)
579
+
580
+ The framework includes the official zero-dependency client `client/wsrpc.ts`:
581
+
582
+ ```typescript
583
+ import { BinaryWSRPC, wsConnected, wsStatus } from './wsrpc';
584
+
585
+ const rpc = new BinaryWSRPC('wss://api.example.com/ws');
586
+ await rpc.connect();
587
+
588
+ // 1. Standard typed RPC call
589
+ const profile = await rpc.call<UserProfile>('user.get_profile', { user_id: 42 });
590
+ console.log('User profile:', profile.name);
591
+
592
+ // 2. Multi-return: Progress streaming for long-running workloads
593
+ const report = await rpc.callStream<ReportResult>(
594
+ 'reports.generate',
595
+ { period: '2026-Q3' },
596
+ (chunk) => {
597
+ console.log(`[${chunk.percent}%] Progress: ${chunk.message}`);
598
+ updateProgressBar(chunk.percent); // Real-time UI progress update!
599
+ }
600
+ );
601
+ console.log('Report ready:', report.download_url);
602
+
603
+ // 3. Receive unsolicited Server Push notifications
604
+ const unsubscribe = rpc.on('chat.new_message', (msg) => {
605
+ console.log(`[${msg.author}]: ${msg.text}`);
606
+ messagesList.update(items => [...items, msg]);
607
+ });
608
+
609
+ // 4. Symmetric RPC: Server initiates an interactive prompt on the client
610
+ rpc.registerMethod('ui.confirm', async (params) => {
611
+ const isApproved = await showConfirmationModal(params.title, params.message);
612
+ return { confirmed: isApproved }; // Transmitted back to the server!
613
+ });
614
+ ```
615
+
616
+ > 📖 **For in-depth UI framework integrations (Svelte, React, Vue), error handling, and unsubscription patterns, see: [docs/core.md](docs/core.md#8-typescriptjavascript-client-clientwsrpcts)**.
617
+
618
+ ---
619
+
620
+ ## 🌟 What's New in v0.3.3
621
+
622
+ * 🚀 **Unified `FerroApp` Application Class**:
623
+ * Single-call Code-First initialization configuring secrets, database, CORS, and static file hosting.
624
+ * Native Zero-Copy static file serving via Rust Granian `proto.response_file`.
625
+ * Path traversal protection when serving files from `static_dir`.
626
+ * Automatic CORS preflight (`OPTIONS`) and `Access-Control-Allow-*` header handling.
627
+ * Integrated `app.run(host, port, workers)` for clean programmatic startups without shell scripts.
628
+ * ⚡ **Kwargs Auto-Unpacking in `@rpc_method` / `@app.rpc`**:
629
+ * Handlers can define clean signatures with type hints and defaults: `async def fn(session, a: int, b: str = "default")`.
630
+ * JSON-RPC `params` dictionaries are mapped directly into keyword arguments.
631
+ * 🛡 **Access Control & `public=True`**:
632
+ * Guest connections are restricted to `login.*` methods by default.
633
+ * Public endpoints for unauthenticated users are declared explicitly with `@rpc_method("name", public=True)`.
634
+ * 🔒 **Enhanced Security & Cryptography**:
635
+ * Default PBKDF2 iterations increased from 100,000 to **600,000** following OWASP standards.
636
+ * Side-channel timing attack protection: password verification hardened using `hmac.compare_digest`.
637
+ * RSA key generation offloaded to threadpool with cache rotation to eliminate event-loop starvation.
638
+ * 📦 **Streaming File Uploads (Granian RSGI)**:
639
+ * Chunked request body ingestion via `proto.read()` directly to disk ensuring constant $O(1)$ memory usage.
640
+ * Upload authorization verification via `/auth-check-upload` supporting `Authorization: Bearer <token>`.
641
+ * 🌐 **Scalability Backplane**:
642
+ * Added `pyferro.core.backplane` module with `BaseBackplane` contract and `MemoryBackplane`.
643
+ * Multi-worker startup warning logged when `workers > 1` is configured with in-memory state.
644
+ * 🤖 **AI-Native Guide `AGENTS.md`**:
645
+ * Included a dedicated LLM instruction file in the repository root to guarantee zero-hallucination agentic development.
646
+
647
+ ---
648
+
649
+ ## 📄 License
650
+ This project is licensed under the **MIT License**.
651
+ Free for commercial use, modification, and distribution.