prodkit 0.2.0__tar.gz → 0.2.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 (43) hide show
  1. {prodkit-0.2.0 → prodkit-0.2.1}/CHANGELOG.md +7 -0
  2. {prodkit-0.2.0 → prodkit-0.2.1}/PKG-INFO +34 -10
  3. {prodkit-0.2.0 → prodkit-0.2.1}/README.md +33 -9
  4. {prodkit-0.2.0 → prodkit-0.2.1}/pyproject.toml +1 -1
  5. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/__init__.py +1 -1
  6. {prodkit-0.2.0 → prodkit-0.2.1}/.gitignore +0 -0
  7. {prodkit-0.2.0 → prodkit-0.2.1}/LICENSE +0 -0
  8. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/cli/__init__.py +0 -0
  9. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/cli/app.py +0 -0
  10. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/cli/loader.py +0 -0
  11. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/contracts/__init__.py +0 -0
  12. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/contracts/plugin.py +0 -0
  13. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/core/__init__.py +0 -0
  14. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/core/config.py +0 -0
  15. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/core/context.py +0 -0
  16. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/core/doctor.py +0 -0
  17. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/core/event_bus.py +0 -0
  18. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/core/exceptions.py +0 -0
  19. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/core/lifecycle.py +0 -0
  20. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/core/plugin_manager.py +0 -0
  21. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/core/production.py +0 -0
  22. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/core/registry.py +0 -0
  23. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/plugins/__init__.py +0 -0
  24. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/plugins/compression/__init__.py +0 -0
  25. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/plugins/cors/__init__.py +0 -0
  26. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/plugins/errors/__init__.py +0 -0
  27. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/plugins/health/__init__.py +0 -0
  28. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/plugins/logging/__init__.py +0 -0
  29. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/plugins/rate_limit/__init__.py +0 -0
  30. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/plugins/request_id/__init__.py +0 -0
  31. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/plugins/security/__init__.py +0 -0
  32. {prodkit-0.2.0 → prodkit-0.2.1}/src/prodkit/py.typed +0 -0
  33. {prodkit-0.2.0 → prodkit-0.2.1}/tests/__init__.py +0 -0
  34. {prodkit-0.2.0 → prodkit-0.2.1}/tests/conftest.py +0 -0
  35. {prodkit-0.2.0 → prodkit-0.2.1}/tests/integration/__init__.py +0 -0
  36. {prodkit-0.2.0 → prodkit-0.2.1}/tests/integration/test_cli.py +0 -0
  37. {prodkit-0.2.0 → prodkit-0.2.1}/tests/integration/test_logging.py +0 -0
  38. {prodkit-0.2.0 → prodkit-0.2.1}/tests/integration/test_production.py +0 -0
  39. {prodkit-0.2.0 → prodkit-0.2.1}/tests/unit/__init__.py +0 -0
  40. {prodkit-0.2.0 → prodkit-0.2.1}/tests/unit/test_config.py +0 -0
  41. {prodkit-0.2.0 → prodkit-0.2.1}/tests/unit/test_doctor.py +0 -0
  42. {prodkit-0.2.0 → prodkit-0.2.1}/tests/unit/test_kernel.py +0 -0
  43. {prodkit-0.2.0 → prodkit-0.2.1}/tests/unit/test_rate_limit.py +0 -0
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.1] - 2026-07-23
11
+
12
+ ### Changed
13
+ - README polish: PyPI/Python badges, table of contents, `prodkit[cli]` install
14
+ note, rate-limiting shown in the config examples, and a `doctor()` hook in the
15
+ plugin-authoring example. Docs-only release (no code changes).
16
+
10
17
  ## [0.2.0] - 2026-07-22
11
18
 
12
19
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prodkit
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: The production framework for FastAPI. One line. Production ready.
5
5
  Project-URL: Homepage, https://github.com/Pushkarpant/PRODKIT
6
6
  Project-URL: Documentation, https://github.com/Pushkarpant/PRODKIT#readme
@@ -61,14 +61,24 @@ Production(app)
61
61
 
62
62
  That's it. Your app now has security headers, structured JSON logging with
63
63
  request-ID correlation, RFC 9457 error responses, Kubernetes-ready health
64
- endpoints, and gzip compression — configured to current best practice,
65
- hardened for production, and pleasant in development.
64
+ endpoints, gzip compression, and opt-in rate limiting — configured to current
65
+ best practice, hardened for production, and pleasant in development. Then run
66
+ [`prodkit doctor`](#cli--prodkit-doctor) to score how production-ready it is.
66
67
 
68
+ [![PyPI](https://img.shields.io/pypi/v/prodkit.svg)](https://pypi.org/project/prodkit/)
69
+ [![Python](https://img.shields.io/pypi/pyversions/prodkit.svg)](https://pypi.org/project/prodkit/)
67
70
  [![CI](https://github.com/Pushkarpant/PRODKIT/actions/workflows/ci.yml/badge.svg)](https://github.com/Pushkarpant/PRODKIT/actions/workflows/ci.yml)
68
71
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/Pushkarpant/PRODKIT/blob/main/LICENSE)
69
72
 
70
73
  ---
71
74
 
75
+ **Contents:** [Why](#why) · [Install](#installation) · [Quick Start](#quick-start) ·
76
+ [What You Get](#what-you-get) · [Configuration](#configuration) ·
77
+ [Plugins](#writing-a-plugin) · [CLI / doctor](#cli--prodkit-doctor) ·
78
+ [Status & Roadmap](#project-status)
79
+
80
+ ---
81
+
72
82
  ## Why
73
83
 
74
84
  Every production FastAPI service re-implements the same ~500 lines of glue:
@@ -84,11 +94,13 @@ evolve, `pip install -U prodkit` updates every app you own.
84
94
  [**`pip install prodkit`**](https://pypi.org/project/prodkit/)
85
95
 
86
96
  ```bash
87
- pip install prodkit
97
+ pip install prodkit # the library
98
+ pip install "prodkit[cli]" # + the `prodkit doctor` CLI (typer + rich)
88
99
  ```
89
100
 
90
101
  Requires Python 3.10+ and FastAPI 0.110+. The base install depends only on
91
- FastAPI and Pydantic — nothing else.
102
+ FastAPI and Pydantic — nothing else. Optional extras: `cli` (CLI),
103
+ `brotli` (Brotli compression).
92
104
 
93
105
  ## Quick Start
94
106
 
@@ -116,7 +128,9 @@ x-content-type-options: nosniff
116
128
  x-frame-options: DENY
117
129
  strict-transport-security: max-age=63072000; includeSubDomains
118
130
  referrer-policy: strict-origin-when-cross-origin
119
- ...
131
+ permissions-policy: camera=(), microphone=(), geolocation=()
132
+ x-xss-protection: 0
133
+ content-type: application/json
120
134
  ```
121
135
 
122
136
  For local development, flip the profile — pretty console logs, debug error
@@ -158,6 +172,7 @@ Production(
158
172
  cors={"origins": ["https://app.example.com"]}, # dict = configure & enable
159
173
  compression=False, # bool = toggle
160
174
  security={"trusted_hosts": ["api.example.com"]},
175
+ rate_limit={"default": "100/minute"}, # opt-in per-IP limiting
161
176
  )
162
177
  ```
163
178
 
@@ -181,6 +196,10 @@ level = "INFO"
181
196
  [cors]
182
197
  enabled = true
183
198
  origins = ["https://app.example.com"]
199
+
200
+ [rate_limit]
201
+ enabled = true
202
+ default = "100/minute"
184
203
  ```
185
204
 
186
205
  ### Fail-fast, refuse-unsafe
@@ -202,7 +221,7 @@ not warned about:
202
221
  ## Writing a Plugin
203
222
 
204
223
  ```python
205
- from prodkit import Check, Plugin, Production
224
+ from prodkit import Audit, Check, Plugin, Production
206
225
 
207
226
  class DatabasePlugin(Plugin):
208
227
  name = "database"
@@ -214,13 +233,18 @@ class DatabasePlugin(Plugin):
214
233
  async def shutdown(self, ctx):
215
234
  await self.pool.close()
216
235
 
217
- def checks(self, ctx):
236
+ def checks(self, ctx): # runtime readiness → /ready
218
237
  return [Check(name="database", passed=self.pool.is_alive())]
219
238
 
239
+ def doctor(self, ctx): # static audit → prodkit doctor
240
+ return [Audit(name="Database pool",
241
+ status="ok", detail="connection pool configured")]
242
+
220
243
  Production(app, plugins=[DatabasePlugin()])
221
244
  ```
222
245
 
223
- Your check now shows up in `/ready` automatically. Plugins can declare
246
+ Your `checks()` result now shows up in `/ready` automatically, and your
247
+ `doctor()` findings roll into the `prodkit doctor` score. Plugins can declare
224
248
  `requires = ("other-plugin",)` and the kernel activates them in dependency
225
249
  order — cycles and missing dependencies fail at boot.
226
250
 
@@ -277,7 +301,7 @@ plugins score too.
277
301
 
278
302
  ## Project Status
279
303
 
280
- **v0.2.0 — alpha.** Core kernel, eight built-in plugins (incl. rate-limiting),
304
+ **v0.2.1 — alpha.** Core kernel, eight built-in plugins (incl. rate-limiting),
281
305
  the `prodkit doctor` CLI with a production-readiness score, strict mypy, CI
282
306
  across Python 3.10–3.13.
283
307
 
@@ -14,14 +14,24 @@ Production(app)
14
14
 
15
15
  That's it. Your app now has security headers, structured JSON logging with
16
16
  request-ID correlation, RFC 9457 error responses, Kubernetes-ready health
17
- endpoints, and gzip compression — configured to current best practice,
18
- hardened for production, and pleasant in development.
17
+ endpoints, gzip compression, and opt-in rate limiting — configured to current
18
+ best practice, hardened for production, and pleasant in development. Then run
19
+ [`prodkit doctor`](#cli--prodkit-doctor) to score how production-ready it is.
19
20
 
21
+ [![PyPI](https://img.shields.io/pypi/v/prodkit.svg)](https://pypi.org/project/prodkit/)
22
+ [![Python](https://img.shields.io/pypi/pyversions/prodkit.svg)](https://pypi.org/project/prodkit/)
20
23
  [![CI](https://github.com/Pushkarpant/PRODKIT/actions/workflows/ci.yml/badge.svg)](https://github.com/Pushkarpant/PRODKIT/actions/workflows/ci.yml)
21
24
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/Pushkarpant/PRODKIT/blob/main/LICENSE)
22
25
 
23
26
  ---
24
27
 
28
+ **Contents:** [Why](#why) · [Install](#installation) · [Quick Start](#quick-start) ·
29
+ [What You Get](#what-you-get) · [Configuration](#configuration) ·
30
+ [Plugins](#writing-a-plugin) · [CLI / doctor](#cli--prodkit-doctor) ·
31
+ [Status & Roadmap](#project-status)
32
+
33
+ ---
34
+
25
35
  ## Why
26
36
 
27
37
  Every production FastAPI service re-implements the same ~500 lines of glue:
@@ -37,11 +47,13 @@ evolve, `pip install -U prodkit` updates every app you own.
37
47
  [**`pip install prodkit`**](https://pypi.org/project/prodkit/)
38
48
 
39
49
  ```bash
40
- pip install prodkit
50
+ pip install prodkit # the library
51
+ pip install "prodkit[cli]" # + the `prodkit doctor` CLI (typer + rich)
41
52
  ```
42
53
 
43
54
  Requires Python 3.10+ and FastAPI 0.110+. The base install depends only on
44
- FastAPI and Pydantic — nothing else.
55
+ FastAPI and Pydantic — nothing else. Optional extras: `cli` (CLI),
56
+ `brotli` (Brotli compression).
45
57
 
46
58
  ## Quick Start
47
59
 
@@ -69,7 +81,9 @@ x-content-type-options: nosniff
69
81
  x-frame-options: DENY
70
82
  strict-transport-security: max-age=63072000; includeSubDomains
71
83
  referrer-policy: strict-origin-when-cross-origin
72
- ...
84
+ permissions-policy: camera=(), microphone=(), geolocation=()
85
+ x-xss-protection: 0
86
+ content-type: application/json
73
87
  ```
74
88
 
75
89
  For local development, flip the profile — pretty console logs, debug error
@@ -111,6 +125,7 @@ Production(
111
125
  cors={"origins": ["https://app.example.com"]}, # dict = configure & enable
112
126
  compression=False, # bool = toggle
113
127
  security={"trusted_hosts": ["api.example.com"]},
128
+ rate_limit={"default": "100/minute"}, # opt-in per-IP limiting
114
129
  )
115
130
  ```
116
131
 
@@ -134,6 +149,10 @@ level = "INFO"
134
149
  [cors]
135
150
  enabled = true
136
151
  origins = ["https://app.example.com"]
152
+
153
+ [rate_limit]
154
+ enabled = true
155
+ default = "100/minute"
137
156
  ```
138
157
 
139
158
  ### Fail-fast, refuse-unsafe
@@ -155,7 +174,7 @@ not warned about:
155
174
  ## Writing a Plugin
156
175
 
157
176
  ```python
158
- from prodkit import Check, Plugin, Production
177
+ from prodkit import Audit, Check, Plugin, Production
159
178
 
160
179
  class DatabasePlugin(Plugin):
161
180
  name = "database"
@@ -167,13 +186,18 @@ class DatabasePlugin(Plugin):
167
186
  async def shutdown(self, ctx):
168
187
  await self.pool.close()
169
188
 
170
- def checks(self, ctx):
189
+ def checks(self, ctx): # runtime readiness → /ready
171
190
  return [Check(name="database", passed=self.pool.is_alive())]
172
191
 
192
+ def doctor(self, ctx): # static audit → prodkit doctor
193
+ return [Audit(name="Database pool",
194
+ status="ok", detail="connection pool configured")]
195
+
173
196
  Production(app, plugins=[DatabasePlugin()])
174
197
  ```
175
198
 
176
- Your check now shows up in `/ready` automatically. Plugins can declare
199
+ Your `checks()` result now shows up in `/ready` automatically, and your
200
+ `doctor()` findings roll into the `prodkit doctor` score. Plugins can declare
177
201
  `requires = ("other-plugin",)` and the kernel activates them in dependency
178
202
  order — cycles and missing dependencies fail at boot.
179
203
 
@@ -230,7 +254,7 @@ plugins score too.
230
254
 
231
255
  ## Project Status
232
256
 
233
- **v0.2.0 — alpha.** Core kernel, eight built-in plugins (incl. rate-limiting),
257
+ **v0.2.1 — alpha.** Core kernel, eight built-in plugins (incl. rate-limiting),
234
258
  the `prodkit doctor` CLI with a production-readiness score, strict mypy, CI
235
259
  across Python 3.10–3.13.
236
260
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "prodkit"
7
- version = "0.2.0"
7
+ version = "0.2.1"
8
8
  description = "The production framework for FastAPI. One line. Production ready."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -34,7 +34,7 @@ from prodkit.plugins import builtin_plugins
34
34
  # root — the kernel itself never imports from prodkit.plugins.
35
35
  set_builtin_factory(builtin_plugins)
36
36
 
37
- __version__ = "0.2.0"
37
+ __version__ = "0.2.1"
38
38
 
39
39
  __all__ = [
40
40
  "Audit",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes