parbaked 0.4.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.
Files changed (42) hide show
  1. parbaked-0.4.0/.gitignore +40 -0
  2. parbaked-0.4.0/LICENSE +21 -0
  3. parbaked-0.4.0/PKG-INFO +204 -0
  4. parbaked-0.4.0/README.md +168 -0
  5. parbaked-0.4.0/examples/README.md +17 -0
  6. parbaked-0.4.0/pyproject.toml +84 -0
  7. parbaked-0.4.0/src/parbaked/__init__.py +20 -0
  8. parbaked-0.4.0/src/parbaked/admin.py +216 -0
  9. parbaked-0.4.0/src/parbaked/app.py +234 -0
  10. parbaked-0.4.0/src/parbaked/auth/__init__.py +12 -0
  11. parbaked-0.4.0/src/parbaked/auth/deps.py +67 -0
  12. parbaked-0.4.0/src/parbaked/auth/jwt.py +51 -0
  13. parbaked-0.4.0/src/parbaked/auth/models.py +54 -0
  14. parbaked-0.4.0/src/parbaked/auth/passwords.py +18 -0
  15. parbaked-0.4.0/src/parbaked/auth/router.py +312 -0
  16. parbaked-0.4.0/src/parbaked/auth/tokens.py +104 -0
  17. parbaked-0.4.0/src/parbaked/cli/__init__.py +1 -0
  18. parbaked-0.4.0/src/parbaked/cli/main.py +177 -0
  19. parbaked-0.4.0/src/parbaked/cli/templates/starter/.env.example +22 -0
  20. parbaked-0.4.0/src/parbaked/cli/templates/starter/Dockerfile +14 -0
  21. parbaked-0.4.0/src/parbaked/cli/templates/starter/Makefile +59 -0
  22. parbaked-0.4.0/src/parbaked/cli/templates/starter/README.md +59 -0
  23. parbaked-0.4.0/src/parbaked/cli/templates/starter/fly.toml.tpl +33 -0
  24. parbaked-0.4.0/src/parbaked/cli/templates/starter/gitignore.tpl +17 -0
  25. parbaked-0.4.0/src/parbaked/cli/templates/starter/main.py +36 -0
  26. parbaked-0.4.0/src/parbaked/cli/templates/starter/pyproject.toml.tpl +10 -0
  27. parbaked-0.4.0/src/parbaked/cli/templates/starter/templates/base.html +22 -0
  28. parbaked-0.4.0/src/parbaked/cli/templates/starter/templates/dashboard.html +40 -0
  29. parbaked-0.4.0/src/parbaked/cli/templates/starter/templates/home.html +11 -0
  30. parbaked-0.4.0/src/parbaked/cli/templates/starter/templates/login.html +55 -0
  31. parbaked-0.4.0/src/parbaked/cli/templates/starter/templates/signup.html +69 -0
  32. parbaked-0.4.0/src/parbaked/config.py +85 -0
  33. parbaked-0.4.0/src/parbaked/email/__init__.py +12 -0
  34. parbaked-0.4.0/src/parbaked/email/base.py +19 -0
  35. parbaked-0.4.0/src/parbaked/email/console.py +37 -0
  36. parbaked-0.4.0/src/parbaked/email/smtp.py +37 -0
  37. parbaked-0.4.0/src/parbaked/email/templates.py +92 -0
  38. parbaked-0.4.0/src/parbaked/frontend/LoginForm.tsx +78 -0
  39. parbaked-0.4.0/src/parbaked/frontend/PendingScreen.tsx +15 -0
  40. parbaked-0.4.0/src/parbaked/frontend/README.md +32 -0
  41. parbaked-0.4.0/src/parbaked/frontend/SignupForm.tsx +105 -0
  42. parbaked-0.4.0/src/parbaked/ratelimit.py +33 -0
@@ -0,0 +1,40 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ *.egg
9
+
10
+ # Virtual environments
11
+ .venv/
12
+ venv/
13
+ env/
14
+
15
+ # Testing / coverage
16
+ .pytest_cache/
17
+ .coverage
18
+ htmlcov/
19
+ .tox/
20
+ .mypy_cache/
21
+ .ruff_cache/
22
+
23
+ # IDE
24
+ .idea/
25
+ .vscode/
26
+ *.swp
27
+ *.swo
28
+
29
+ # Env / secrets
30
+ .env
31
+ .env.local
32
+ *.db
33
+ *.sqlite
34
+
35
+ # OS
36
+ .DS_Store
37
+ Thumbs.db
38
+
39
+ # Build artifacts
40
+ *.log
parbaked-0.4.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sam Leighton
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.
@@ -0,0 +1,204 @@
1
+ Metadata-Version: 2.4
2
+ Name: parbaked
3
+ Version: 0.4.0
4
+ Summary: A par-baked starter for PoC apps: signup-with-approval auth, rate limiting, and (soon) deploy scaffolding for fly.io
5
+ Project-URL: Homepage, https://github.com/saml7n/parbaked
6
+ Project-URL: Repository, https://github.com/saml7n/parbaked
7
+ Project-URL: Issues, https://github.com/saml7n/parbaked/issues
8
+ Author: Sam Leighton
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: auth,fastapi,fly.io,poc,scaffold,starter
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Framework :: FastAPI
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Internet :: WWW/HTTP
18
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: bcrypt>=4.1
21
+ Requires-Dist: email-validator>=2.1
22
+ Requires-Dist: fastapi>=0.110
23
+ Requires-Dist: jinja2>=3.1
24
+ Requires-Dist: pydantic-settings>=2.1
25
+ Requires-Dist: pydantic>=2.5
26
+ Requires-Dist: pyjwt>=2.8
27
+ Requires-Dist: slowapi>=0.1.9
28
+ Requires-Dist: sqlmodel>=0.0.16
29
+ Requires-Dist: typer>=0.12
30
+ Provides-Extra: dev
31
+ Requires-Dist: httpx>=0.27; extra == 'dev'
32
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
33
+ Requires-Dist: pytest>=8.0; extra == 'dev'
34
+ Requires-Dist: ruff>=0.4; extra == 'dev'
35
+ Description-Content-Type: text/markdown
36
+
37
+ # parbaked
38
+
39
+ **A par-baked starter for FastAPI PoCs.** Signup with admin approval, rate limiting, and an admin dashboard — set up in one line.
40
+
41
+ > If you ship PoCs on fly.io, two things eventually bite you: anyone on the internet can spin up accounts in a loop (and run up your bill), and you write the same auth boilerplate every time. parbaked is the slice between "I have an idea" and "this is safe to put online."
42
+
43
+ ## 30-second quickstart
44
+
45
+ ```bash
46
+ uvx parbaked new myapp
47
+ cd myapp
48
+ make dev
49
+ ```
50
+
51
+ Open `http://localhost:8000`, sign up. Open `http://localhost:8000/auth/admin` and log in as `admin` with the password printed in your terminal. Approve yourself. Log in. Done.
52
+
53
+ You now have a working PoC with:
54
+
55
+ - Signup + login + JWT sessions
56
+ - Admin-approval gate (nobody gets in until you click approve)
57
+ - Built-in admin dashboard with pending/active/rejected queues
58
+ - Per-IP rate limiting (5/min signup, 10/min login by default)
59
+ - SQLite DB and secrets auto-created on first run
60
+
61
+ ## Add to an existing FastAPI app
62
+
63
+ ```python
64
+ from fastapi import FastAPI
65
+ from parbaked import Parbaked
66
+
67
+ app = FastAPI()
68
+ parbaked = Parbaked(app) # ← that's the whole setup
69
+ ```
70
+
71
+ That gives you `/auth/signup`, `/auth/login`, `/auth/me`, `/auth/admin`, and approval magic links. On first boot you'll see:
72
+
73
+ ```
74
+ ╔════════════════════════════════════════════════════════════════╗
75
+ ║ parbaked v0.2.0 is running ║
76
+ ╠════════════════════════════════════════════════════════════════╣
77
+ ║ Sign up at: http://localhost:8000/auth/signup ║
78
+ ║ Admin panel: http://localhost:8000/auth/admin ║
79
+ ║ Admin user: admin ║
80
+ ║ Admin pass: z703EwDKmEKL9S6SaO39uuRq ║
81
+ ║ Email out: Console (printed below) ║
82
+ ║ Database: sqlite:///./parbaked.db ║
83
+ ║ ║
84
+ ║ ⚠ Auto-generated secrets stored in .parbaked.json ║
85
+ ║ Add it to .gitignore. For prod, set env vars instead. ║
86
+ ╚════════════════════════════════════════════════════════════════╝
87
+ ```
88
+
89
+ Protect your own routes:
90
+
91
+ ```python
92
+ from fastapi import Depends
93
+
94
+ @app.get("/profile")
95
+ def profile(user = Depends(parbaked.current_user)):
96
+ return {"email": user.email, "name": user.name}
97
+ ```
98
+
99
+ ## Why an approval gate?
100
+
101
+ Without one:
102
+
103
+ - Anyone on the internet can sign up to your PoC
104
+ - Even with rate limits, sustained traffic can autoscale you onto a bill
105
+ - You can't show it to a friend without also showing it to bots
106
+
107
+ With one:
108
+
109
+ - Pending accounts can't log in. Period.
110
+ - You see every signup. Click approve in your inbox or in the dashboard.
111
+ - Bots can fill the database with junk, but they can't *do* anything — and rate limits cap the junk.
112
+
113
+ The approval flow uses **HMAC-signed magic links** (no DB state) AND a **built-in web dashboard** (HTTP-basic-auth gated). Use whichever you prefer — email's nicer for low volume, the dashboard's nicer when you want to see the queue.
114
+
115
+ ## Configuration
116
+
117
+ Everything has sensible defaults. Override via env vars (prefix `PARBAKED_`) or by passing args to `Parbaked()`:
118
+
119
+ | Env var | Default | What it does |
120
+ |---|---|---|
121
+ | `JWT_SECRET` | *(auto-generated)* | Session token signing key |
122
+ | `APPROVAL_TOKEN_SECRET` | *(auto-generated)* | Magic-link signing key |
123
+ | `ADMIN_PASSWORD` | *(auto-generated)* | Dashboard login password (user is always `admin`) |
124
+ | `ADMIN_EMAIL` | unset | Where signup-approval emails go (dashboard works without this) |
125
+ | `APP_NAME` | `"My App"` | Used in email subjects |
126
+ | `APP_URL` | `http://localhost:8000` | Public URL for magic links |
127
+ | `EMAIL_TRANSPORT` | `console` | `console` (dev) or `smtp` |
128
+ | `SMTP_HOST` / `_PORT` / `_USER` / `_PASSWORD` / `_FROM` | — | SMTP credentials if transport is `smtp` |
129
+ | `RATELIMIT_SIGNUP` | `5/minute` | Per-IP signup limit |
130
+ | `RATELIMIT_LOGIN` | `10/minute` | Per-IP login limit |
131
+ | `DATABASE_URL` | `sqlite:///./parbaked.db` | Standard SQLAlchemy URL |
132
+
133
+ Auto-generated secrets get persisted to `.parbaked.json` (chmod 600). In production, set them as env vars instead.
134
+
135
+ ## Security posture
136
+
137
+ What protects you from a bill:
138
+
139
+ - **Per-IP rate limits** on signup and login (slowapi)
140
+ - **No email enumeration** — signup with an existing email and login with a wrong password return generic errors
141
+ - **Approval gate** — even if someone gets past the rate limit, they can't do anything until you click approve
142
+ - **bcrypt** for passwords, **HS256 JWT** for sessions, **audience-scoped JWT** for magic links so a session token can never be replayed as approval (and vice versa)
143
+
144
+ What's on the roadmap (and isn't here yet):
145
+
146
+ - **v0.3** — Deploy scaffolding: opinionated `Dockerfile`, `fly.toml` with `auto_stop_machines = "stop"` + hard max-machines cap, `make tunnel` recipe using `cloudflared tunnel --url http://localhost:8000` (no auth needed; ephemeral trycloudflare.com URL).
147
+ - **v0.4** — Pluggable CAPTCHA on signup (Cloudflare Turnstile / hCaptcha).
148
+ - **v0.5** — Resend / SendGrid / SES email transports.
149
+
150
+ ## React/TypeScript components
151
+
152
+ Drop-in components for if you're building a React frontend. They ship as **source** in `src/parbaked/frontend/` — copy them into your `web/src/`:
153
+
154
+ - `SignupForm.tsx`
155
+ - `LoginForm.tsx`
156
+ - `PendingScreen.tsx`
157
+
158
+ Tailwind classes, no internal dependencies. See `src/parbaked/frontend/README.md`.
159
+
160
+ ## When you need more control
161
+
162
+ The one-call `Parbaked(app)` is the simple case. If you want to wire pieces yourself:
163
+
164
+ ```python
165
+ from parbaked import ParbakedConfig
166
+ from parbaked.auth import build_auth_router, make_current_user
167
+ from parbaked.email import ConsoleEmail
168
+ from parbaked.ratelimit import install_rate_limiting
169
+
170
+ config = ParbakedConfig(jwt_secret="...", admin_email="you@example.com")
171
+ limiter = install_rate_limiting(app, config)
172
+ app.include_router(
173
+ build_auth_router(config, get_session, ConsoleEmail(), limiter=limiter)
174
+ )
175
+ current_user = make_current_user(config, get_session)
176
+ ```
177
+
178
+ Same building blocks, no smart defaults. Use this when you want a custom email transport, your own admin dashboard, or to wire parbaked into a non-trivial app structure.
179
+
180
+ ## Install
181
+
182
+ ```bash
183
+ pip install parbaked
184
+ # or
185
+ uv add parbaked
186
+ ```
187
+
188
+ Requires Python 3.11+.
189
+
190
+ ## Develop / contribute
191
+
192
+ ```bash
193
+ git clone https://github.com/saml7n/parbaked
194
+ cd parbaked
195
+ uv venv && source .venv/bin/activate
196
+ uv pip install -e ".[dev]"
197
+ pytest
198
+ ```
199
+
200
+ Issues and PRs welcome.
201
+
202
+ ## License
203
+
204
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,168 @@
1
+ # parbaked
2
+
3
+ **A par-baked starter for FastAPI PoCs.** Signup with admin approval, rate limiting, and an admin dashboard — set up in one line.
4
+
5
+ > If you ship PoCs on fly.io, two things eventually bite you: anyone on the internet can spin up accounts in a loop (and run up your bill), and you write the same auth boilerplate every time. parbaked is the slice between "I have an idea" and "this is safe to put online."
6
+
7
+ ## 30-second quickstart
8
+
9
+ ```bash
10
+ uvx parbaked new myapp
11
+ cd myapp
12
+ make dev
13
+ ```
14
+
15
+ Open `http://localhost:8000`, sign up. Open `http://localhost:8000/auth/admin` and log in as `admin` with the password printed in your terminal. Approve yourself. Log in. Done.
16
+
17
+ You now have a working PoC with:
18
+
19
+ - Signup + login + JWT sessions
20
+ - Admin-approval gate (nobody gets in until you click approve)
21
+ - Built-in admin dashboard with pending/active/rejected queues
22
+ - Per-IP rate limiting (5/min signup, 10/min login by default)
23
+ - SQLite DB and secrets auto-created on first run
24
+
25
+ ## Add to an existing FastAPI app
26
+
27
+ ```python
28
+ from fastapi import FastAPI
29
+ from parbaked import Parbaked
30
+
31
+ app = FastAPI()
32
+ parbaked = Parbaked(app) # ← that's the whole setup
33
+ ```
34
+
35
+ That gives you `/auth/signup`, `/auth/login`, `/auth/me`, `/auth/admin`, and approval magic links. On first boot you'll see:
36
+
37
+ ```
38
+ ╔════════════════════════════════════════════════════════════════╗
39
+ ║ parbaked v0.2.0 is running ║
40
+ ╠════════════════════════════════════════════════════════════════╣
41
+ ║ Sign up at: http://localhost:8000/auth/signup ║
42
+ ║ Admin panel: http://localhost:8000/auth/admin ║
43
+ ║ Admin user: admin ║
44
+ ║ Admin pass: z703EwDKmEKL9S6SaO39uuRq ║
45
+ ║ Email out: Console (printed below) ║
46
+ ║ Database: sqlite:///./parbaked.db ║
47
+ ║ ║
48
+ ║ ⚠ Auto-generated secrets stored in .parbaked.json ║
49
+ ║ Add it to .gitignore. For prod, set env vars instead. ║
50
+ ╚════════════════════════════════════════════════════════════════╝
51
+ ```
52
+
53
+ Protect your own routes:
54
+
55
+ ```python
56
+ from fastapi import Depends
57
+
58
+ @app.get("/profile")
59
+ def profile(user = Depends(parbaked.current_user)):
60
+ return {"email": user.email, "name": user.name}
61
+ ```
62
+
63
+ ## Why an approval gate?
64
+
65
+ Without one:
66
+
67
+ - Anyone on the internet can sign up to your PoC
68
+ - Even with rate limits, sustained traffic can autoscale you onto a bill
69
+ - You can't show it to a friend without also showing it to bots
70
+
71
+ With one:
72
+
73
+ - Pending accounts can't log in. Period.
74
+ - You see every signup. Click approve in your inbox or in the dashboard.
75
+ - Bots can fill the database with junk, but they can't *do* anything — and rate limits cap the junk.
76
+
77
+ The approval flow uses **HMAC-signed magic links** (no DB state) AND a **built-in web dashboard** (HTTP-basic-auth gated). Use whichever you prefer — email's nicer for low volume, the dashboard's nicer when you want to see the queue.
78
+
79
+ ## Configuration
80
+
81
+ Everything has sensible defaults. Override via env vars (prefix `PARBAKED_`) or by passing args to `Parbaked()`:
82
+
83
+ | Env var | Default | What it does |
84
+ |---|---|---|
85
+ | `JWT_SECRET` | *(auto-generated)* | Session token signing key |
86
+ | `APPROVAL_TOKEN_SECRET` | *(auto-generated)* | Magic-link signing key |
87
+ | `ADMIN_PASSWORD` | *(auto-generated)* | Dashboard login password (user is always `admin`) |
88
+ | `ADMIN_EMAIL` | unset | Where signup-approval emails go (dashboard works without this) |
89
+ | `APP_NAME` | `"My App"` | Used in email subjects |
90
+ | `APP_URL` | `http://localhost:8000` | Public URL for magic links |
91
+ | `EMAIL_TRANSPORT` | `console` | `console` (dev) or `smtp` |
92
+ | `SMTP_HOST` / `_PORT` / `_USER` / `_PASSWORD` / `_FROM` | — | SMTP credentials if transport is `smtp` |
93
+ | `RATELIMIT_SIGNUP` | `5/minute` | Per-IP signup limit |
94
+ | `RATELIMIT_LOGIN` | `10/minute` | Per-IP login limit |
95
+ | `DATABASE_URL` | `sqlite:///./parbaked.db` | Standard SQLAlchemy URL |
96
+
97
+ Auto-generated secrets get persisted to `.parbaked.json` (chmod 600). In production, set them as env vars instead.
98
+
99
+ ## Security posture
100
+
101
+ What protects you from a bill:
102
+
103
+ - **Per-IP rate limits** on signup and login (slowapi)
104
+ - **No email enumeration** — signup with an existing email and login with a wrong password return generic errors
105
+ - **Approval gate** — even if someone gets past the rate limit, they can't do anything until you click approve
106
+ - **bcrypt** for passwords, **HS256 JWT** for sessions, **audience-scoped JWT** for magic links so a session token can never be replayed as approval (and vice versa)
107
+
108
+ What's on the roadmap (and isn't here yet):
109
+
110
+ - **v0.3** — Deploy scaffolding: opinionated `Dockerfile`, `fly.toml` with `auto_stop_machines = "stop"` + hard max-machines cap, `make tunnel` recipe using `cloudflared tunnel --url http://localhost:8000` (no auth needed; ephemeral trycloudflare.com URL).
111
+ - **v0.4** — Pluggable CAPTCHA on signup (Cloudflare Turnstile / hCaptcha).
112
+ - **v0.5** — Resend / SendGrid / SES email transports.
113
+
114
+ ## React/TypeScript components
115
+
116
+ Drop-in components for if you're building a React frontend. They ship as **source** in `src/parbaked/frontend/` — copy them into your `web/src/`:
117
+
118
+ - `SignupForm.tsx`
119
+ - `LoginForm.tsx`
120
+ - `PendingScreen.tsx`
121
+
122
+ Tailwind classes, no internal dependencies. See `src/parbaked/frontend/README.md`.
123
+
124
+ ## When you need more control
125
+
126
+ The one-call `Parbaked(app)` is the simple case. If you want to wire pieces yourself:
127
+
128
+ ```python
129
+ from parbaked import ParbakedConfig
130
+ from parbaked.auth import build_auth_router, make_current_user
131
+ from parbaked.email import ConsoleEmail
132
+ from parbaked.ratelimit import install_rate_limiting
133
+
134
+ config = ParbakedConfig(jwt_secret="...", admin_email="you@example.com")
135
+ limiter = install_rate_limiting(app, config)
136
+ app.include_router(
137
+ build_auth_router(config, get_session, ConsoleEmail(), limiter=limiter)
138
+ )
139
+ current_user = make_current_user(config, get_session)
140
+ ```
141
+
142
+ Same building blocks, no smart defaults. Use this when you want a custom email transport, your own admin dashboard, or to wire parbaked into a non-trivial app structure.
143
+
144
+ ## Install
145
+
146
+ ```bash
147
+ pip install parbaked
148
+ # or
149
+ uv add parbaked
150
+ ```
151
+
152
+ Requires Python 3.11+.
153
+
154
+ ## Develop / contribute
155
+
156
+ ```bash
157
+ git clone https://github.com/saml7n/parbaked
158
+ cd parbaked
159
+ uv venv && source .venv/bin/activate
160
+ uv pip install -e ".[dev]"
161
+ pytest
162
+ ```
163
+
164
+ Issues and PRs welcome.
165
+
166
+ ## License
167
+
168
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,17 @@
1
+ # parbaked examples
2
+
3
+ Runnable, version-pinned examples. Each file is a complete FastAPI app — copy, paste, run.
4
+
5
+ Run any of them with:
6
+
7
+ ```bash
8
+ uv run uvicorn examples.<filename>:app --reload
9
+ ```
10
+
11
+ | File | What it shows |
12
+ |---|---|
13
+ | [`minimal.py`](minimal.py) | The 4-line setup. Zero config. |
14
+ | [`with_smtp.py`](with_smtp.py) | Real email via SMTP (Resend / SES / Gmail / anything). |
15
+ | [`protected_routes.py`](protected_routes.py) | Using `parbaked.current_user` to gate your own routes. |
16
+ | [`per_user_data.py`](per_user_data.py) | Adding a per-user table that joins on `users.id` — the right way to extend the schema. |
17
+ | [`custom_emails.py`](custom_emails.py) | Overriding the email body copy without forking parbaked. |
@@ -0,0 +1,84 @@
1
+ [project]
2
+ name = "parbaked"
3
+ version = "0.4.0"
4
+ description = "A par-baked starter for PoC apps: signup-with-approval auth, rate limiting, and (soon) deploy scaffolding for fly.io"
5
+ readme = "README.md"
6
+ license = { text = "MIT" }
7
+ authors = [{ name = "Sam Leighton" }]
8
+ requires-python = ">=3.11"
9
+ keywords = ["fastapi", "auth", "starter", "scaffold", "fly.io", "poc"]
10
+ classifiers = [
11
+ "Development Status :: 3 - Alpha",
12
+ "Framework :: FastAPI",
13
+ "License :: OSI Approved :: MIT License",
14
+ "Programming Language :: Python :: 3.11",
15
+ "Programming Language :: Python :: 3.12",
16
+ "Topic :: Internet :: WWW/HTTP",
17
+ "Topic :: Software Development :: Libraries :: Application Frameworks",
18
+ ]
19
+ dependencies = [
20
+ "fastapi>=0.110",
21
+ "sqlmodel>=0.0.16",
22
+ "pydantic>=2.5",
23
+ "pydantic-settings>=2.1",
24
+ "bcrypt>=4.1",
25
+ "pyjwt>=2.8",
26
+ "slowapi>=0.1.9",
27
+ "email-validator>=2.1",
28
+ "typer>=0.12",
29
+ "jinja2>=3.1",
30
+ ]
31
+
32
+ [project.optional-dependencies]
33
+ dev = [
34
+ "pytest>=8.0",
35
+ "pytest-asyncio>=0.23",
36
+ "httpx>=0.27",
37
+ "ruff>=0.4",
38
+ ]
39
+
40
+ [project.scripts]
41
+ parbaked = "parbaked.cli.main:app"
42
+
43
+ [project.urls]
44
+ Homepage = "https://github.com/saml7n/parbaked"
45
+ Repository = "https://github.com/saml7n/parbaked"
46
+ Issues = "https://github.com/saml7n/parbaked/issues"
47
+
48
+ [build-system]
49
+ requires = ["hatchling"]
50
+ build-backend = "hatchling.build"
51
+
52
+ [tool.hatch.build.targets.wheel]
53
+ packages = ["src/parbaked"]
54
+
55
+ [tool.hatch.build.targets.sdist]
56
+ include = ["src/parbaked", "README.md", "LICENSE"]
57
+
58
+ [tool.pytest.ini_options]
59
+ testpaths = ["tests"]
60
+ asyncio_mode = "auto"
61
+
62
+ [tool.ruff]
63
+ line-length = 100
64
+ target-version = "py311"
65
+
66
+ [tool.ruff.lint]
67
+ select = ["E", "F", "I", "UP", "B", "SIM"]
68
+ extend-safe-fixes = ["UP"]
69
+
70
+ [tool.ruff.lint.flake8-bugbear]
71
+ # These callables in default arguments are the canonical patterns for FastAPI
72
+ # / Typer and are intentional, not a B008 bug.
73
+ extend-immutable-calls = [
74
+ "fastapi.Depends",
75
+ "fastapi.Header",
76
+ "fastapi.Query",
77
+ "fastapi.Cookie",
78
+ "fastapi.Body",
79
+ "fastapi.Path",
80
+ "fastapi.File",
81
+ "fastapi.Form",
82
+ "typer.Argument",
83
+ "typer.Option",
84
+ ]
@@ -0,0 +1,20 @@
1
+ """parbaked — a par-baked starter for PoC apps.
2
+
3
+ Public API re-exports the most commonly used pieces so consumers can do:
4
+
5
+ from parbaked import ParbakedConfig, auth_router, get_current_user
6
+ """
7
+
8
+ __version__ = "0.4.0"
9
+
10
+ from parbaked.app import Parbaked
11
+ from parbaked.auth.deps import make_current_user
12
+ from parbaked.auth.router import build_auth_router
13
+ from parbaked.config import ParbakedConfig
14
+
15
+ __all__ = [
16
+ "Parbaked",
17
+ "ParbakedConfig",
18
+ "build_auth_router",
19
+ "make_current_user",
20
+ ]