prodkit 0.3.0__tar.gz → 0.3.1__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 (53) hide show
  1. prodkit-0.3.1/PKG-INFO +440 -0
  2. prodkit-0.3.1/README.md +370 -0
  3. {prodkit-0.3.0 → prodkit-0.3.1}/pyproject.toml +10 -1
  4. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/__init__.py +1 -1
  5. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/plugins/tracing/__init__.py +1 -1
  6. prodkit-0.3.0/PKG-INFO +0 -370
  7. prodkit-0.3.0/README.md +0 -300
  8. {prodkit-0.3.0 → prodkit-0.3.1}/.gitignore +0 -0
  9. {prodkit-0.3.0 → prodkit-0.3.1}/CHANGELOG.md +0 -0
  10. {prodkit-0.3.0 → prodkit-0.3.1}/LICENSE +0 -0
  11. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/cli/__init__.py +0 -0
  12. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/cli/app.py +0 -0
  13. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/cli/loader.py +0 -0
  14. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/contracts/__init__.py +0 -0
  15. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/contracts/plugin.py +0 -0
  16. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/core/__init__.py +0 -0
  17. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/core/config.py +0 -0
  18. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/core/context.py +0 -0
  19. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/core/doctor.py +0 -0
  20. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/core/event_bus.py +0 -0
  21. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/core/exceptions.py +0 -0
  22. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/core/lifecycle.py +0 -0
  23. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/core/plugin_manager.py +0 -0
  24. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/core/production.py +0 -0
  25. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/core/registry.py +0 -0
  26. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/plugins/__init__.py +0 -0
  27. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/plugins/_redis.py +0 -0
  28. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/plugins/cache/__init__.py +0 -0
  29. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/plugins/compression/__init__.py +0 -0
  30. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/plugins/cors/__init__.py +0 -0
  31. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/plugins/errors/__init__.py +0 -0
  32. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/plugins/health/__init__.py +0 -0
  33. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/plugins/logging/__init__.py +0 -0
  34. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/plugins/metrics/__init__.py +0 -0
  35. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/plugins/rate_limit/__init__.py +0 -0
  36. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/plugins/rate_limit/backends.py +0 -0
  37. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/plugins/request_id/__init__.py +0 -0
  38. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/plugins/security/__init__.py +0 -0
  39. {prodkit-0.3.0 → prodkit-0.3.1}/src/prodkit/py.typed +0 -0
  40. {prodkit-0.3.0 → prodkit-0.3.1}/tests/__init__.py +0 -0
  41. {prodkit-0.3.0 → prodkit-0.3.1}/tests/conftest.py +0 -0
  42. {prodkit-0.3.0 → prodkit-0.3.1}/tests/integration/__init__.py +0 -0
  43. {prodkit-0.3.0 → prodkit-0.3.1}/tests/integration/test_cli.py +0 -0
  44. {prodkit-0.3.0 → prodkit-0.3.1}/tests/integration/test_logging.py +0 -0
  45. {prodkit-0.3.0 → prodkit-0.3.1}/tests/integration/test_production.py +0 -0
  46. {prodkit-0.3.0 → prodkit-0.3.1}/tests/unit/__init__.py +0 -0
  47. {prodkit-0.3.0 → prodkit-0.3.1}/tests/unit/test_cache.py +0 -0
  48. {prodkit-0.3.0 → prodkit-0.3.1}/tests/unit/test_config.py +0 -0
  49. {prodkit-0.3.0 → prodkit-0.3.1}/tests/unit/test_doctor.py +0 -0
  50. {prodkit-0.3.0 → prodkit-0.3.1}/tests/unit/test_kernel.py +0 -0
  51. {prodkit-0.3.0 → prodkit-0.3.1}/tests/unit/test_metrics.py +0 -0
  52. {prodkit-0.3.0 → prodkit-0.3.1}/tests/unit/test_rate_limit.py +0 -0
  53. {prodkit-0.3.0 → prodkit-0.3.1}/tests/unit/test_tracing.py +0 -0
prodkit-0.3.1/PKG-INFO ADDED
@@ -0,0 +1,440 @@
1
+ Metadata-Version: 2.5
2
+ Name: prodkit
3
+ Version: 0.3.1
4
+ Summary: The production framework for FastAPI. One line. Production ready.
5
+ Project-URL: Homepage, https://github.com/Pushkarpant/PRODKIT
6
+ Project-URL: Documentation, https://github.com/Pushkarpant/PRODKIT#readme
7
+ Project-URL: Repository, https://github.com/Pushkarpant/PRODKIT
8
+ Project-URL: Changelog, https://github.com/Pushkarpant/PRODKIT/blob/main/CHANGELOG.md
9
+ Project-URL: Issues, https://github.com/Pushkarpant/PRODKIT/issues
10
+ Author-email: Pushkar Pant <pantpushkar4@gmail.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: fastapi,health-check,logging,metrics,middleware,observability,opentelemetry,production,security,tracing
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Framework :: FastAPI
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
24
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.10
27
+ Requires-Dist: fastapi>=0.110
28
+ Requires-Dist: pydantic-settings>=2.1
29
+ Requires-Dist: pydantic>=2.5
30
+ Requires-Dist: tomli>=2.0; python_version < '3.11'
31
+ Provides-Extra: all
32
+ Requires-Dist: brotli-asgi>=1.4; extra == 'all'
33
+ Requires-Dist: opentelemetry-api>=1.20; extra == 'all'
34
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.20; extra == 'all'
35
+ Requires-Dist: opentelemetry-sdk>=1.20; extra == 'all'
36
+ Requires-Dist: prometheus-client>=0.20; extra == 'all'
37
+ Requires-Dist: redis>=5.0; extra == 'all'
38
+ Requires-Dist: rich>=13; extra == 'all'
39
+ Requires-Dist: typer>=0.12; extra == 'all'
40
+ Provides-Extra: brotli
41
+ Requires-Dist: brotli-asgi>=1.4; extra == 'brotli'
42
+ Provides-Extra: cli
43
+ Requires-Dist: rich>=13; extra == 'cli'
44
+ Requires-Dist: typer>=0.12; extra == 'cli'
45
+ Provides-Extra: dev
46
+ Requires-Dist: anyio[trio]>=4.0; extra == 'dev'
47
+ Requires-Dist: fakeredis[lua]>=2.21; extra == 'dev'
48
+ Requires-Dist: httpx>=0.27; extra == 'dev'
49
+ Requires-Dist: import-linter>=2.0; extra == 'dev'
50
+ Requires-Dist: mypy>=1.11; extra == 'dev'
51
+ Requires-Dist: opentelemetry-api>=1.20; extra == 'dev'
52
+ Requires-Dist: opentelemetry-sdk>=1.20; extra == 'dev'
53
+ Requires-Dist: prometheus-client>=0.20; extra == 'dev'
54
+ Requires-Dist: pytest-anyio>=0.0.0; extra == 'dev'
55
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
56
+ Requires-Dist: pytest>=8.0; extra == 'dev'
57
+ Requires-Dist: rich>=13; extra == 'dev'
58
+ Requires-Dist: ruff>=0.6; extra == 'dev'
59
+ Requires-Dist: tomli>=2.0; extra == 'dev'
60
+ Requires-Dist: typer>=0.12; extra == 'dev'
61
+ Provides-Extra: metrics
62
+ Requires-Dist: prometheus-client>=0.20; extra == 'metrics'
63
+ Provides-Extra: otel
64
+ Requires-Dist: opentelemetry-api>=1.20; extra == 'otel'
65
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.20; extra == 'otel'
66
+ Requires-Dist: opentelemetry-sdk>=1.20; extra == 'otel'
67
+ Provides-Extra: redis
68
+ Requires-Dist: redis>=5.0; extra == 'redis'
69
+ Description-Content-Type: text/markdown
70
+
71
+ <div align="center">
72
+
73
+ # ⚡ ProdKit
74
+
75
+ ### *One line. Production ready.*
76
+
77
+ The production engine for **[FastAPI](https://fastapi.tiangolo.com/)**.
78
+
79
+ ```python
80
+ from fastapi import FastAPI
81
+ from prodkit import Production
82
+
83
+ app = FastAPI()
84
+ Production(app) # 👈 That's it. Production hardened.
85
+ ```
86
+
87
+ [![PyPI Version](https://img.shields.io/pypi/v/prodkit.svg?style=for-the-badge&color=blue)](https://pypi.org/project/prodkit/)
88
+ [![Python Versions](https://img.shields.io/pypi/pyversions/prodkit.svg?style=for-the-badge&color=snake)](https://pypi.org/project/prodkit/)
89
+ [![Build Status](https://img.shields.io/github/actions/workflow/status/Pushkarpant/PRODKIT/ci.yml?branch=main&style=for-the-badge&label=CI)](https://github.com/Pushkarpant/PRODKIT/actions/workflows/ci.yml)
90
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](https://github.com/Pushkarpant/PRODKIT/blob/main/LICENSE)
91
+ [![Code Style: Ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg?style=for-the-badge)](https://github.com/astral-sh/ruff)
92
+
93
+ [⚡ Quick Start](#quick-start) · [📦 Installation](#installation) · [✨ What You Get](#what-you-get) · [🩺 CLI Doctor](#cli-doctor) · [🎛️ Configuration](#configuration) · [🔌 Plugins](#plugins) · [🗺️ Roadmap](#roadmap)
94
+
95
+ ---
96
+
97
+ </div>
98
+
99
+ <br/>
100
+
101
+ ## 🎯 The Problem & Solution
102
+
103
+ <details open>
104
+ <summary><b>💡 Why does ProdKit exist? (Click to toggle comparison)</b></summary>
105
+
106
+ <br/>
107
+
108
+ Every FastAPI service that goes to production re-implements the exact same **~500 lines of glue code**: security headers, JSON access logs, request-ID correlation, RFC 9457 error normalization, Kubernetes health probes, CORS safety, and rate-limiting.
109
+
110
+ FastAPI is a micro-framework and deliberately omits this. **ProdKit provides the production batteries in a single import.**
111
+
112
+ | Without ProdKit ❌ | With ProdKit (`Production(app)`) ✅ |
113
+ |---|---|
114
+ | 🔴 Plain error 500s leak python stack traces to clients | 🛡️ RFC 9457 `problem+json` — 500s opaque to users, traced in logs |
115
+ | 🔴 Ad-hoc log lines without correlation IDs | 📋 Structured JSON logs with auto-injected `X-Request-ID` |
116
+ | 🔴 Missing security headers (vulnerable to clickjacking/sniffing) | 🔒 OWASP-hardened headers (`nosniff`, `DENY`, HSTS, CSP) |
117
+ | 🔴 Wildcard CORS combined with credentials footgun | 🚫 Refuses unsafe prod configs at startup with named key error |
118
+ | 🔴 Hand-rolled `/health` endpoints that don't check dependencies | 🏥 Native `/health`, `/live`, and `/ready` with dependency checks |
119
+ | 🔴 Hard to update when security standards evolve | 🔄 `pip install -U prodkit` upgrades all your apps in seconds |
120
+
121
+ </details>
122
+
123
+ ---
124
+
125
+ <a id="quick-start"></a>
126
+ ## 💻 Interactive Quick Start
127
+
128
+ ### 1️⃣ Run Your App
129
+ ```python
130
+ # main.py
131
+ from fastapi import FastAPI
132
+ from prodkit import Production
133
+
134
+ app = FastAPI(title="Payment Service")
135
+ Production(app) # Auto-configures production profile
136
+
137
+
138
+ @app.get("/charge")
139
+ def charge():
140
+ return {"status": "success"}
141
+ ```
142
+
143
+ ```bash
144
+ uvicorn main:app
145
+ ```
146
+
147
+ ### 2️⃣ Inspect Production Headers & Request Tracing
148
+
149
+ <details open>
150
+ <summary><b>🔍 <code>curl -i http://localhost:8000/charge</code> (Click to inspect output)</b></summary>
151
+
152
+ ```http
153
+ HTTP/1.1 200 OK
154
+ content-type: application/json
155
+ x-request-id: 26fdc49565614c2a9ef1a3b8d4e0f712
156
+ x-content-type-options: nosniff
157
+ x-frame-options: DENY
158
+ strict-transport-security: max-age=63072000; includeSubDomains
159
+ referrer-policy: strict-origin-when-cross-origin
160
+ permissions-policy: camera=(), microphone=(), geolocation=()
161
+ x-xss-protection: 0
162
+
163
+ {"status":"success"}
164
+ ```
165
+ </details>
166
+
167
+ <details>
168
+ <summary><b>🏥 <code>curl -i http://localhost:8000/ready</code> (Kubernetes Readiness Check)</b></summary>
169
+
170
+ ```http
171
+ HTTP/1.1 200 OK
172
+ content-type: application/json
173
+
174
+ {
175
+ "status": "ready",
176
+ "checks": [
177
+ { "name": "request-id", "passed": true },
178
+ { "name": "logging", "passed": true },
179
+ { "name": "security", "passed": true }
180
+ ]
181
+ }
182
+ ```
183
+ </details>
184
+
185
+ ---
186
+
187
+ <a id="installation"></a>
188
+ ## 📦 Installation
189
+
190
+ ```bash
191
+ # Base framework (zero extra dependencies)
192
+ pip install prodkit
193
+
194
+ # Recommended extras
195
+ pip install "prodkit[cli]" # Includes `prodkit doctor` CLI (typer + rich)
196
+ pip install "prodkit[metrics]" # Prometheus /metrics endpoint
197
+ pip install "prodkit[otel]" # OpenTelemetry tracing
198
+ pip install "prodkit[redis]" # Distributed Redis rate-limiting & cache
199
+ pip install "prodkit[all]" # All available plugins and extras
200
+ ```
201
+
202
+ | Extra | Adds | Dependencies |
203
+ |---|---|---|
204
+ | `cli` | `prodkit doctor`, `inspect`, `init` commands | `typer`, `rich` |
205
+ | `metrics` | Prometheus metrics endpoint (`/metrics`) | `prometheus-client` |
206
+ | `otel` | W3C distributed tracing with OpenTelemetry | `opentelemetry-api`, `opentelemetry-sdk` |
207
+ | `redis` | Multi-worker rate limiting & distributed cache | `redis` / `fakeredis` |
208
+ | `brotli` | High-ratio Brotli response compression | `brotli` |
209
+ | `all` | Everything above | All optional extras |
210
+
211
+ ---
212
+
213
+ <a id="what-you-get"></a>
214
+ ## ✨ What You Get Out of the Box
215
+
216
+ ProdKit includes **11 modular built-in plugins**, organized with explicit middleware execution priorities:
217
+
218
+ ```text
219
+ 100 RequestID (Outer-most: generates/extracts X-Request-ID)
220
+ 200 Structured Logging (Correlates log lines with Request ID & timing)
221
+ 290 OpenTelemetry (Request tracing spans & W3C context propagation)
222
+ 300 Prometheus Metrics (Exposes /metrics with route-template labels)
223
+ 400 Security Headers (OWASP nosniff, HSTS, X-Frame-Options, CSP)
224
+ 500 CORS Safety (Strict origin validation, refuses wildcard+creds)
225
+ 600 Rate Limiting (Per-IP window limits, memory or Redis backend)
226
+ 700 Compression (Gzip & Brotli response compression)
227
+ [ Your FastAPI App Code ]
228
+ ```
229
+
230
+ <details>
231
+ <summary><b>📖 Expand Complete Feature Matrix</b></summary>
232
+
233
+ <br/>
234
+
235
+ | Icon | Feature | Description | Default |
236
+ |:---:|---|---|:---:|
237
+ | 🆔 | **Request IDs** | `X-Request-ID` attached to every response, bound to async context for log correlation. | `On` |
238
+ | 📋 | **Structured Logging** | Production JSON logs (Datadog/CloudWatch/Loki ready) or colorful console logs in dev. | `On` |
239
+ | 🛡️ | **Security Headers** | `nosniff`, `X-Frame-Options: DENY`, `Strict-Transport-Security`, `Referrer-Policy`. | `On` |
240
+ | 🚨 | **Error Normalization** | [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) `problem+json` standard. 500 tracebacks hidden in prod. | `On` |
241
+ | ❤️ | **Health Probes** | K8s endpoints: `/health` (liveness), `/live`, and `/ready` (aggregates plugin checks). | `On` |
242
+ | 🌐 | **CORS Guard** | Prevents insecure wildcard credentials (`origins=["*"]` + `credentials=True` fails boot). | `Configured` |
243
+ | 📦 | **Compression** | Automatic Gzip (and optional Brotli) compression for payloads > 500 bytes. | `On` |
244
+ | 🚦 | **Rate Limiting** | Per-IP sliding limits (`100/minute`), returns `429 Too Many Requests` with `Retry-After`. | `Opt-in` |
245
+ | 📊 | **Prometheus Metrics** | Scrapeable `/metrics` endpoint (request totals, duration histograms, in-flight gauges). | `Opt-in` |
246
+ | 🗄️ | **Cache Service** | Injection-ready cache (`MemoryCache` or `RedisCache`) registered in app context. | `Opt-in` |
247
+ | 🔭 | **OpenTelemetry** | Auto-instrumentation of HTTP requests with OTLP/Console exporters & W3C headers. | `Opt-in` |
248
+
249
+ </details>
250
+
251
+ ---
252
+
253
+ <a id="cli-doctor"></a>
254
+ ## 🩺 CLI — `prodkit doctor`
255
+
256
+ Run static & runtime security audits against your app and get a **0–100 Production Score**:
257
+
258
+ ```bash
259
+ prodkit doctor --app main:app
260
+ ```
261
+
262
+ ```text
263
+ Production Readiness Audit
264
+ ┌───┬────────────────────────┬─────────────────────┬──────────────────────────┐
265
+ │ ✔ │ Security headers │ nosniff, X-Frame... │ │
266
+ │ ✔ │ Structured logging │ json @ INFO │ │
267
+ │ ✔ │ Error normalization │ 500s opaque │ │
268
+ │ ✔ │ Request IDs │ enabled (header) │ │
269
+ │ ✔ │ Health probes │ /health /ready │ │
270
+ │ ⚠ │ Rate limiting │ memory backend │ set backend="redis" ... │
271
+ │ ⚠ │ Content-Security-Policy│ default-src missing │ set CSP for web apps │
272
+ └───┴────────────────────────┴─────────────────────┴──────────────────────────┘
273
+ Production Score: 88 / 100 [ 2 Warning(s) ]
274
+ ```
275
+
276
+ ### 🚦 Gate CI/CD Builds
277
+ Enforce production standards in GitHub Actions or GitLab CI:
278
+
279
+ ```bash
280
+ # Fails CI build (exit code 1) if production readiness score falls below threshold
281
+ prodkit doctor --app main:app --strict --min-score 90
282
+ ```
283
+
284
+ <details>
285
+ <summary><b>🛠️ More CLI Commands (<code>inspect</code>, <code>plugins</code>, <code>init</code>)</b></summary>
286
+
287
+ <br/>
288
+
289
+ ```bash
290
+ # View resolved configuration, active plugins, and middleware execution stack:
291
+ prodkit inspect --app main:app
292
+
293
+ # List all active plugins and their implemented lifecycle hooks:
294
+ prodkit plugins --app main:app
295
+
296
+ # Scaffold starter prodkit.toml configuration file:
297
+ prodkit init --example
298
+ ```
299
+
300
+ </details>
301
+
302
+ ---
303
+
304
+ <a id="configuration"></a>
305
+ ## 🎛️ Configuration
306
+
307
+ ProdKit merges configuration across **4 priority layers** (highest wins):
308
+
309
+ ```text
310
+ Python Args ──► Environment Vars ──► prodkit.toml ──► Profile Defaults
311
+ (Highest) (Lowest)
312
+ ```
313
+
314
+ <details open>
315
+ <summary><b>⚙️ Choose Configuration Style (Click to tab)</b></summary>
316
+
317
+ #### Option A: Python Arguments
318
+ ```python
319
+ Production(
320
+ app,
321
+ environment="production",
322
+ cors={"origins": ["https://app.example.com"]},
323
+ rate_limit={"default": "100/minute", "backend": "redis"},
324
+ metrics=True,
325
+ tracing={"exporter": "otlp", "sample_rate": 0.2},
326
+ )
327
+ ```
328
+
329
+ #### Option B: `prodkit.toml`
330
+ ```toml
331
+ [prodkit]
332
+ environment = "production"
333
+
334
+ [logging]
335
+ level = "INFO"
336
+ format = "json"
337
+
338
+ [rate_limit]
339
+ enabled = true
340
+ default = "100/minute"
341
+ backend = "redis"
342
+
343
+ [metrics]
344
+ enabled = true
345
+ path = "/metrics"
346
+ ```
347
+
348
+ #### Option C: Environment Variables (`__` for nested keys)
349
+ ```bash
350
+ export PRODKIT_ENVIRONMENT=production
351
+ export PRODKIT_LOGGING__LEVEL=WARNING
352
+ export PRODKIT_RATE_LIMIT__BACKEND=redis
353
+ export PRODKIT_METRICS__ENABLED=true
354
+ ```
355
+
356
+ </details>
357
+
358
+ ---
359
+
360
+ <a id="plugins"></a>
361
+ ## 🔌 Writing a Custom Plugin
362
+
363
+ All features in ProdKit (including built-ins) are plugins implementing the `Plugin` contract.
364
+
365
+ ```python
366
+ from prodkit import Plugin, Check, Audit, Production
367
+
368
+
369
+ class DatabaseHealthPlugin(Plugin):
370
+ name = "db-health"
371
+ requires = [] # Dependency ordering
372
+
373
+ async def startup(self, ctx):
374
+ # Async resource setup
375
+ ctx.registry.provide("db_pool", await connect_db())
376
+
377
+ async def shutdown(self, ctx):
378
+ pool = ctx.registry.get("db_pool")
379
+ await pool.close()
380
+
381
+ def checks(self, ctx):
382
+ # Feeds into K8s /ready probe
383
+ is_connected = ctx.registry.get("db_pool").is_active()
384
+ return [Check(name="database", passed=is_connected)]
385
+
386
+ def doctor(self, ctx):
387
+ # Feeds into `prodkit doctor` score
388
+ return [Audit(name="Database Connection", status="ok", detail="Pool initialized")]
389
+
390
+
391
+ Production(app, plugins=[DatabaseHealthPlugin()])
392
+ ```
393
+
394
+ ---
395
+
396
+ ## 🛡️ Plays Nice With Your App
397
+
398
+ - **Zero Lock-in**: Mutates/wraps the FastAPI instance. Remove `Production(app)` anytime to return to plain FastAPI.
399
+ - **Lifespan Composition**: Your custom `@asynccontextmanager` lifespan is preserved and wrapped (Plugin startup → App lifespan → Plugin shutdown).
400
+ - **Your Code Wins**: If your route explicitly sets a header or error handler, your application code takes precedence.
401
+
402
+ ---
403
+
404
+ <a id="roadmap"></a>
405
+ ## 🗺️ Project Status & Roadmap
406
+
407
+ | Version | Status | Highlights |
408
+ |---|---|---|
409
+ | **v0.1.0** | ✅ Released | Core kernel, security headers, JSON logs, RFC 9457 error normalization, `/health` |
410
+ | **v0.2.0** | ✅ Released | `prodkit doctor` CLI, readiness score, in-memory rate limiting |
411
+ | **v0.3.0** | ✅ **Current** | **Prometheus metrics, Redis backends, OpenTelemetry tracing, Cache service** |
412
+ | **v0.4.0** | 🚧 Next | `prodkit generate` (Dockerfile, nginx, docker-compose, GitHub Actions CI) |
413
+ | **v0.5.0** | 📅 Planned | Public Plugin SDK & Ecosystem (`prodkit-sentry`, entry-point discovery) |
414
+ | **v1.0.0** | 🎯 Milestone | Frozen Public API, LTS release, Production case studies |
415
+
416
+ ---
417
+
418
+ ## 🤝 Contributing & License
419
+
420
+ We welcome contributions! Please see [CONTRIBUTING.md](https://github.com/Pushkarpant/PRODKIT/blob/main/CONTRIBUTING.md) and [SECURITY.md](https://github.com/Pushkarpant/PRODKIT/blob/main/SECURITY.md).
421
+
422
+ ```bash
423
+ git clone https://github.com/Pushkarpant/PRODKIT.git
424
+ cd PRODKIT
425
+ python -m venv .venv && source .venv/bin/activate # on Windows: .venv\Scripts\activate
426
+ pip install -e ".[dev,all]"
427
+ pytest
428
+ ```
429
+
430
+ Distributed under the **[MIT License](https://github.com/Pushkarpant/PRODKIT/blob/main/LICENSE)**.
431
+
432
+ <br/>
433
+
434
+ <div align="center">
435
+
436
+ **Built with ❤️ by [Pushkar Pant](https://github.com/Pushkarpant)**
437
+
438
+ *FastAPI builds APIs. ProdKit makes them production-ready.*
439
+
440
+ </div>