regstack 0.2.2__tar.gz → 0.2.4__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 (184) hide show
  1. {regstack-0.2.2 → regstack-0.2.4}/CHANGELOG.md +29 -0
  2. {regstack-0.2.2 → regstack-0.2.4}/PKG-INFO +1 -1
  3. regstack-0.2.4/docs/api.md +278 -0
  4. {regstack-0.2.2 → regstack-0.2.4}/docs/architecture.md +0 -1
  5. {regstack-0.2.2 → regstack-0.2.4}/docs/changelog.md +61 -0
  6. {regstack-0.2.2 → regstack-0.2.4}/pyproject.toml +1 -1
  7. regstack-0.2.4/src/regstack/app.py +322 -0
  8. regstack-0.2.4/src/regstack/auth/clock.py +73 -0
  9. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/auth/dependencies.py +47 -5
  10. regstack-0.2.4/src/regstack/auth/jwt.py +256 -0
  11. regstack-0.2.4/src/regstack/auth/lockout.py +119 -0
  12. regstack-0.2.4/src/regstack/auth/password.py +65 -0
  13. regstack-0.2.4/src/regstack/backends/mongo/repositories/__init__.py +13 -0
  14. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/mongo/repositories/mfa_code_repo.py +0 -3
  15. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/mongo/repositories/pending_repo.py +0 -3
  16. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/mongo/repositories/user_repo.py +0 -3
  17. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/protocols.py +31 -6
  18. regstack-0.2.4/src/regstack/email/base.py +71 -0
  19. regstack-0.2.4/src/regstack/hooks/events.py +98 -0
  20. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/models/_objectid.py +0 -8
  21. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/models/login_attempt.py +2 -2
  22. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/models/mfa_code.py +2 -2
  23. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/models/pending_registration.py +2 -2
  24. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/models/user.py +2 -2
  25. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/routers/__init__.py +21 -1
  26. regstack-0.2.4/src/regstack/sms/base.py +67 -0
  27. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/ui/pages.py +49 -8
  28. regstack-0.2.4/src/regstack/version.py +1 -0
  29. {regstack-0.2.2 → regstack-0.2.4}/tests/unit/test_mfa_code_repo.py +2 -1
  30. {regstack-0.2.2 → regstack-0.2.4}/uv.lock +1 -1
  31. regstack-0.2.2/docs/api.md +0 -184
  32. regstack-0.2.2/src/regstack/app.py +0 -166
  33. regstack-0.2.2/src/regstack/auth/clock.py +0 -29
  34. regstack-0.2.2/src/regstack/auth/jwt.py +0 -145
  35. regstack-0.2.2/src/regstack/auth/lockout.py +0 -59
  36. regstack-0.2.2/src/regstack/auth/password.py +0 -20
  37. regstack-0.2.2/src/regstack/backends/mongo/repositories/__init__.py +0 -27
  38. regstack-0.2.2/src/regstack/email/base.py +0 -23
  39. regstack-0.2.2/src/regstack/hooks/events.py +0 -59
  40. regstack-0.2.2/src/regstack/sms/base.py +0 -24
  41. regstack-0.2.2/src/regstack/version.py +0 -1
  42. {regstack-0.2.2 → regstack-0.2.4}/.github/workflows/publish.yml +0 -0
  43. {regstack-0.2.2 → regstack-0.2.4}/.github/workflows/test.yml +0 -0
  44. {regstack-0.2.2 → regstack-0.2.4}/.gitignore +0 -0
  45. {regstack-0.2.2 → regstack-0.2.4}/.python-version +0 -0
  46. {regstack-0.2.2 → regstack-0.2.4}/.readthedocs.yaml +0 -0
  47. {regstack-0.2.2 → regstack-0.2.4}/CLAUDE.md +0 -0
  48. {regstack-0.2.2 → regstack-0.2.4}/LICENSE +0 -0
  49. {regstack-0.2.2 → regstack-0.2.4}/NOTICE +0 -0
  50. {regstack-0.2.2 → regstack-0.2.4}/README.md +0 -0
  51. {regstack-0.2.2 → regstack-0.2.4}/SECURITY.md +0 -0
  52. {regstack-0.2.2 → regstack-0.2.4}/docs/_static/.gitkeep +0 -0
  53. {regstack-0.2.2 → regstack-0.2.4}/docs/_templates/.gitkeep +0 -0
  54. {regstack-0.2.2 → regstack-0.2.4}/docs/cli.md +0 -0
  55. {regstack-0.2.2 → regstack-0.2.4}/docs/conf.py +0 -0
  56. {regstack-0.2.2 → regstack-0.2.4}/docs/configuration.md +0 -0
  57. {regstack-0.2.2 → regstack-0.2.4}/docs/embedding.md +0 -0
  58. {regstack-0.2.2 → regstack-0.2.4}/docs/index.md +0 -0
  59. {regstack-0.2.2 → regstack-0.2.4}/docs/quickstart.md +0 -0
  60. {regstack-0.2.2 → regstack-0.2.4}/docs/security.md +0 -0
  61. {regstack-0.2.2 → regstack-0.2.4}/docs/theming.md +0 -0
  62. {regstack-0.2.2 → regstack-0.2.4}/examples/_common/__init__.py +0 -0
  63. {regstack-0.2.2 → regstack-0.2.4}/examples/_common/app.py +0 -0
  64. {regstack-0.2.2 → regstack-0.2.4}/examples/mongo/README.md +0 -0
  65. {regstack-0.2.2 → regstack-0.2.4}/examples/mongo/branding/theme.css +0 -0
  66. {regstack-0.2.2 → regstack-0.2.4}/examples/mongo/main.py +0 -0
  67. {regstack-0.2.2 → regstack-0.2.4}/examples/mongo/regstack.toml +0 -0
  68. {regstack-0.2.2 → regstack-0.2.4}/examples/postgres/README.md +0 -0
  69. {regstack-0.2.2 → regstack-0.2.4}/examples/postgres/main.py +0 -0
  70. {regstack-0.2.2 → regstack-0.2.4}/examples/postgres/regstack.toml +0 -0
  71. {regstack-0.2.2 → regstack-0.2.4}/examples/sqlite/README.md +0 -0
  72. {regstack-0.2.2 → regstack-0.2.4}/examples/sqlite/main.py +0 -0
  73. {regstack-0.2.2 → regstack-0.2.4}/examples/sqlite/regstack.toml +0 -0
  74. {regstack-0.2.2 → regstack-0.2.4}/regstack.toml.example +0 -0
  75. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/__init__.py +0 -0
  76. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/auth/__init__.py +0 -0
  77. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/auth/mfa.py +0 -0
  78. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/auth/tokens.py +0 -0
  79. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/__init__.py +0 -0
  80. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/base.py +0 -0
  81. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/factory.py +0 -0
  82. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/mongo/__init__.py +0 -0
  83. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/mongo/backend.py +0 -0
  84. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/mongo/client.py +0 -0
  85. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/mongo/indexes.py +0 -0
  86. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/mongo/repositories/blacklist_repo.py +0 -0
  87. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/mongo/repositories/login_attempt_repo.py +0 -0
  88. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/sql/__init__.py +0 -0
  89. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/sql/backend.py +0 -0
  90. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/sql/migrations/__init__.py +0 -0
  91. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/sql/migrations/env.py +0 -0
  92. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/sql/migrations/script.py.mako +0 -0
  93. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/sql/migrations/versions/0001_initial_schema.py +0 -0
  94. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/sql/repositories/__init__.py +0 -0
  95. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/sql/repositories/blacklist_repo.py +0 -0
  96. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/sql/repositories/login_attempt_repo.py +0 -0
  97. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/sql/repositories/mfa_code_repo.py +0 -0
  98. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/sql/repositories/pending_repo.py +0 -0
  99. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/sql/repositories/user_repo.py +0 -0
  100. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/sql/schema.py +0 -0
  101. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/backends/sql/types.py +0 -0
  102. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/cli/__init__.py +0 -0
  103. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/cli/__main__.py +0 -0
  104. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/cli/_runtime.py +0 -0
  105. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/cli/admin.py +0 -0
  106. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/cli/doctor.py +0 -0
  107. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/cli/init.py +0 -0
  108. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/cli/migrate.py +0 -0
  109. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/config/__init__.py +0 -0
  110. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/config/loader.py +0 -0
  111. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/config/schema.py +0 -0
  112. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/config/secrets.py +0 -0
  113. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/__init__.py +0 -0
  114. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/composer.py +0 -0
  115. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/console.py +0 -0
  116. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/factory.py +0 -0
  117. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/ses.py +0 -0
  118. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/smtp.py +0 -0
  119. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/templates/email_change.html +0 -0
  120. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/templates/email_change.subject.txt +0 -0
  121. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/templates/email_change.txt +0 -0
  122. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/templates/password_reset.html +0 -0
  123. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/templates/password_reset.subject.txt +0 -0
  124. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/templates/password_reset.txt +0 -0
  125. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/templates/sms_login_mfa.txt +0 -0
  126. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/templates/sms_phone_setup.txt +0 -0
  127. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/templates/verification.html +0 -0
  128. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/templates/verification.subject.txt +0 -0
  129. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/email/templates/verification.txt +0 -0
  130. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/hooks/__init__.py +0 -0
  131. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/models/__init__.py +0 -0
  132. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/routers/_schemas.py +0 -0
  133. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/routers/account.py +0 -0
  134. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/routers/admin.py +0 -0
  135. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/routers/login.py +0 -0
  136. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/routers/logout.py +0 -0
  137. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/routers/password.py +0 -0
  138. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/routers/phone.py +0 -0
  139. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/routers/register.py +0 -0
  140. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/routers/verify.py +0 -0
  141. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/sms/__init__.py +0 -0
  142. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/sms/factory.py +0 -0
  143. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/sms/null.py +0 -0
  144. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/sms/sns.py +0 -0
  145. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/sms/twilio.py +0 -0
  146. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/ui/__init__.py +0 -0
  147. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/ui/static/css/core.css +0 -0
  148. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/ui/static/css/theme.css +0 -0
  149. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/ui/static/js/regstack.js +0 -0
  150. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/ui/templates/auth/email_change_confirm.html +0 -0
  151. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/ui/templates/auth/forgot.html +0 -0
  152. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/ui/templates/auth/login.html +0 -0
  153. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/ui/templates/auth/me.html +0 -0
  154. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/ui/templates/auth/mfa_confirm.html +0 -0
  155. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/ui/templates/auth/register.html +0 -0
  156. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/ui/templates/auth/reset.html +0 -0
  157. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/ui/templates/auth/verify.html +0 -0
  158. {regstack-0.2.2 → regstack-0.2.4}/src/regstack/ui/templates/base.html +0 -0
  159. {regstack-0.2.2 → regstack-0.2.4}/tasks.py +0 -0
  160. {regstack-0.2.2 → regstack-0.2.4}/tests/__init__.py +0 -0
  161. {regstack-0.2.2 → regstack-0.2.4}/tests/conftest.py +0 -0
  162. {regstack-0.2.2 → regstack-0.2.4}/tests/integration/__init__.py +0 -0
  163. {regstack-0.2.2 → regstack-0.2.4}/tests/integration/test_account_management.py +0 -0
  164. {regstack-0.2.2 → regstack-0.2.4}/tests/integration/test_admin_router.py +0 -0
  165. {regstack-0.2.2 → regstack-0.2.4}/tests/integration/test_happy_path.py +0 -0
  166. {regstack-0.2.2 → regstack-0.2.4}/tests/integration/test_indexes.py +0 -0
  167. {regstack-0.2.2 → regstack-0.2.4}/tests/integration/test_login_lockout.py +0 -0
  168. {regstack-0.2.2 → regstack-0.2.4}/tests/integration/test_mfa.py +0 -0
  169. {regstack-0.2.2 → regstack-0.2.4}/tests/integration/test_password_reset.py +0 -0
  170. {regstack-0.2.2 → regstack-0.2.4}/tests/integration/test_sql_migrations.py +0 -0
  171. {regstack-0.2.2 → regstack-0.2.4}/tests/integration/test_ui_router.py +0 -0
  172. {regstack-0.2.2 → regstack-0.2.4}/tests/integration/test_verification.py +0 -0
  173. {regstack-0.2.2 → regstack-0.2.4}/tests/unit/__init__.py +0 -0
  174. {regstack-0.2.2 → regstack-0.2.4}/tests/unit/test_base_install_imports.py +0 -0
  175. {regstack-0.2.2 → regstack-0.2.4}/tests/unit/test_cli.py +0 -0
  176. {regstack-0.2.2 → regstack-0.2.4}/tests/unit/test_config_loader.py +0 -0
  177. {regstack-0.2.2 → regstack-0.2.4}/tests/unit/test_jwt.py +0 -0
  178. {regstack-0.2.2 → regstack-0.2.4}/tests/unit/test_lockout.py +0 -0
  179. {regstack-0.2.2 → regstack-0.2.4}/tests/unit/test_mail_composer.py +0 -0
  180. {regstack-0.2.2 → regstack-0.2.4}/tests/unit/test_password.py +0 -0
  181. {regstack-0.2.2 → regstack-0.2.4}/tests/unit/test_ses_backend.py +0 -0
  182. {regstack-0.2.2 → regstack-0.2.4}/tests/unit/test_sms.py +0 -0
  183. {regstack-0.2.2 → regstack-0.2.4}/tests/unit/test_smtp_backend.py +0 -0
  184. {regstack-0.2.2 → regstack-0.2.4}/tests/unit/test_ui_env.py +0 -0
@@ -5,6 +5,35 @@ authoritative copy lives at
5
5
  [`docs/changelog.md`](docs/changelog.md) and is rendered into the
6
6
  Sphinx docs.
7
7
 
8
+ ## 0.2.4 — 2026-04-28
9
+
10
+ **Breaking** — back-compat shims removed:
11
+
12
+ - `RegStack.install_indexes()` (alias for `install_schema()`).
13
+ - `ObjectIdStr` alias for `IdStr` in `regstack.models._objectid`.
14
+ - Re-exports of `UserAlreadyExistsError`,
15
+ `PendingAlreadyExistsError`, `MfaVerifyOutcome`, and
16
+ `MfaVerifyResult` from `regstack.backends.mongo.repositories.*`.
17
+ Their canonical home is `regstack.backends.protocols`.
18
+
19
+ If you import any of these from the old paths, switch to:
20
+ - `RegStack.install_schema()`
21
+ - `from regstack.models._objectid import IdStr`
22
+ - `from regstack.backends.protocols import UserAlreadyExistsError`
23
+ (and friends).
24
+
25
+ The internal mongo `install_indexes(db, config)` function is unchanged.
26
+
27
+ ## 0.2.3 — 2026-04-28
28
+
29
+ Docs-only release. Restructured the API reference around the current
30
+ package layout (post multi-backend refactor) and added Google-style
31
+ docstrings (Args / Returns / Raises) to the public surface — RegStack,
32
+ JwtCodec, PasswordHasher, LockoutService, AuthDependencies,
33
+ HookRegistry, EmailService, SmsService, the router builders, and the
34
+ Clock implementations. Dataclass field docs moved to PEP 258
35
+ attribute docstrings. Sphinx builds clean under `-W` again.
36
+
8
37
  ## 0.2.2 — 2026-04-28
9
38
 
10
39
  Docs-only release. The README and Sphinx docs landing page now lead
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: regstack
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Embeddable user registration, login, and account management for FastAPI apps. SQLite / Postgres / MongoDB.
5
5
  Project-URL: Homepage, https://github.com/jdrumgoole/regstack
6
6
  Project-URL: Repository, https://github.com/jdrumgoole/regstack
@@ -0,0 +1,278 @@
1
+ # API reference
2
+
3
+ Auto-generated from docstrings. The most useful entry point is
4
+ [`regstack.RegStack`](#regstack.app.RegStack); everything else hangs
5
+ off it.
6
+
7
+ This page is organized by what you'd reach for, not by package
8
+ hierarchy. Each section starts with a one-paragraph orientation,
9
+ then the ``autoclass`` / ``autofunction`` directives pull the
10
+ docstrings, signatures, and parameter docs straight off the package
11
+ source.
12
+
13
+ ## Top-level
14
+
15
+ The handful of things you import from `regstack` directly:
16
+
17
+ - [`RegStack`](#regstack.app.RegStack) — the embeddable façade.
18
+ - [`RegStackConfig`](#regstack.config.schema.RegStackConfig) — top-level config.
19
+ - [`EmailConfig`](#regstack.config.schema.EmailConfig) — email-backend sub-config.
20
+ - [`SmsConfig`](#regstack.config.schema.SmsConfig) — SMS-backend sub-config.
21
+
22
+ Most embeddings need only `RegStack` and `RegStackConfig`.
23
+
24
+ ## Façade
25
+
26
+ `RegStack` is the embeddable façade. One per FastAPI application;
27
+ hosts mount its `router` and (optionally) `ui_router`. All collaborators
28
+ — password hasher, JWT codec, repos, hooks bus, email and SMS
29
+ services — hang off the instance.
30
+
31
+ ```{eval-rst}
32
+ .. autoclass:: regstack.app.RegStack
33
+ :members:
34
+ :show-inheritance:
35
+ ```
36
+
37
+ ## Configuration
38
+
39
+ `RegStackConfig` is a `pydantic-settings` model loaded from
40
+ environment variables (`REGSTACK_*`), an optional
41
+ `regstack.secrets.env`, an optional `regstack.toml`, and programmatic
42
+ kwargs — in that priority order. See the
43
+ [Configuration guide](configuration.md) for every field with its
44
+ default.
45
+
46
+ ```{eval-rst}
47
+ .. autoclass:: regstack.config.schema.RegStackConfig
48
+ :members:
49
+ :show-inheritance:
50
+ :exclude-members: model_config, model_fields, model_computed_fields
51
+
52
+ .. autoclass:: regstack.config.schema.EmailConfig
53
+ :members:
54
+ :show-inheritance:
55
+ :exclude-members: model_config, model_fields, model_computed_fields
56
+
57
+ .. autoclass:: regstack.config.schema.SmsConfig
58
+ :members:
59
+ :show-inheritance:
60
+ :exclude-members: model_config, model_fields, model_computed_fields
61
+
62
+ .. autofunction:: regstack.config.loader.load_config
63
+ ```
64
+
65
+ ## Auth primitives
66
+
67
+ The pieces that make authentication work: password hashing (Argon2id),
68
+ JWT issuance and validation with per-purpose derived keys, login
69
+ lockout, and the FastAPI dependency factory. Hosts rarely instantiate
70
+ these directly — they're built and wired by the `RegStack` constructor
71
+ — but the docstrings on the public methods explain the contract.
72
+
73
+ ```{eval-rst}
74
+ .. autoclass:: regstack.auth.password.PasswordHasher
75
+ :members:
76
+
77
+ .. autoclass:: regstack.auth.jwt.JwtCodec
78
+ :members:
79
+
80
+ .. autoclass:: regstack.auth.jwt.TokenPayload
81
+ :members:
82
+
83
+ .. autoexception:: regstack.auth.jwt.TokenError
84
+
85
+ .. autofunction:: regstack.auth.jwt.is_payload_bulk_revoked
86
+
87
+ .. autoclass:: regstack.auth.lockout.LockoutService
88
+ :members:
89
+
90
+ .. autoclass:: regstack.auth.lockout.LockoutDecision
91
+ :members:
92
+
93
+ .. autoclass:: regstack.auth.dependencies.AuthDependencies
94
+ :members:
95
+ ```
96
+
97
+ ### Time
98
+
99
+ Every time-sensitive operation reads `now()` through a `Clock`. Tests
100
+ inject `FrozenClock` to make assertions deterministic.
101
+
102
+ ```{eval-rst}
103
+ .. autoclass:: regstack.auth.clock.Clock
104
+ :members:
105
+
106
+ .. autoclass:: regstack.auth.clock.SystemClock
107
+ :members:
108
+
109
+ .. autoclass:: regstack.auth.clock.FrozenClock
110
+ :members:
111
+ ```
112
+
113
+ ## Backends
114
+
115
+ regstack ships three storage backends behind one set of `Protocol`
116
+ classes: SQLite (default, no infrastructure), PostgreSQL, and MongoDB.
117
+ The active backend is auto-built from `config.database_url`'s URL
118
+ scheme via `build_backend`. Hosts that need to share a connection pool
119
+ with their own application can pass an explicit `Backend` to the
120
+ `RegStack` constructor.
121
+
122
+ ```{eval-rst}
123
+ .. autoclass:: regstack.backends.base.Backend
124
+ :members:
125
+ :show-inheritance:
126
+
127
+ .. autoclass:: regstack.backends.base.BackendKind
128
+ :members:
129
+
130
+ .. autofunction:: regstack.backends.factory.build_backend
131
+
132
+ .. autoclass:: regstack.backends.mongo.MongoBackend
133
+ :members:
134
+ :show-inheritance:
135
+
136
+ .. autoclass:: regstack.backends.sql.SqlBackend
137
+ :members:
138
+ :show-inheritance:
139
+ ```
140
+
141
+ ### Repository protocols
142
+
143
+ The five repository protocols are the contract every backend
144
+ implements. Routers and services depend only on these — switching
145
+ backends is a wiring change, not a code change.
146
+
147
+ ```{eval-rst}
148
+ .. autoclass:: regstack.backends.protocols.UserRepoProtocol
149
+ :members:
150
+
151
+ .. autoclass:: regstack.backends.protocols.PendingRepoProtocol
152
+ :members:
153
+
154
+ .. autoclass:: regstack.backends.protocols.BlacklistRepoProtocol
155
+ :members:
156
+
157
+ .. autoclass:: regstack.backends.protocols.LoginAttemptRepoProtocol
158
+ :members:
159
+
160
+ .. autoclass:: regstack.backends.protocols.MfaCodeRepoProtocol
161
+ :members:
162
+
163
+ .. autoclass:: regstack.backends.protocols.MfaVerifyOutcome
164
+ :members:
165
+
166
+ .. autoclass:: regstack.backends.protocols.MfaVerifyResult
167
+ :members:
168
+
169
+ .. autoexception:: regstack.backends.protocols.UserAlreadyExistsError
170
+
171
+ .. autoexception:: regstack.backends.protocols.PendingAlreadyExistsError
172
+ ```
173
+
174
+ ## Models
175
+
176
+ The persisted data shapes. `BaseUser` is the canonical user document;
177
+ `UserCreate` validates registration input; `UserPublic` is what the
178
+ API returns (omits the password hash). The other models drive
179
+ verification, lockout, and SMS MFA.
180
+
181
+ ```{eval-rst}
182
+ .. autoclass:: regstack.models.user.BaseUser
183
+ :members:
184
+ :exclude-members: model_config, model_fields, model_computed_fields
185
+
186
+ .. autoclass:: regstack.models.user.UserCreate
187
+ :members:
188
+ :exclude-members: model_config, model_fields, model_computed_fields
189
+
190
+ .. autoclass:: regstack.models.user.UserPublic
191
+ :members:
192
+ :exclude-members: model_config, model_fields, model_computed_fields
193
+
194
+ .. autoclass:: regstack.models.pending_registration.PendingRegistration
195
+ :members:
196
+ :exclude-members: model_config, model_fields, model_computed_fields
197
+
198
+ .. autoclass:: regstack.models.login_attempt.LoginAttempt
199
+ :members:
200
+ :exclude-members: model_config, model_fields, model_computed_fields
201
+
202
+ .. autoclass:: regstack.models.mfa_code.MfaCode
203
+ :members:
204
+ :exclude-members: model_config, model_fields, model_computed_fields
205
+ ```
206
+
207
+ ## Email + SMS
208
+
209
+ Pluggable transports for the verification / reset / change-email
210
+ emails and the SMS MFA codes. Implement `EmailService` or `SmsService`
211
+ to plug in a provider that isn't bundled (Postmark, SendGrid,
212
+ MessageBird, …) and pass the instance to `regstack.set_email_backend`
213
+ / `set_sms_backend`.
214
+
215
+ ### Email
216
+
217
+ ```{eval-rst}
218
+ .. autoclass:: regstack.email.base.EmailMessage
219
+ :members:
220
+
221
+ .. autoclass:: regstack.email.base.EmailService
222
+ :members:
223
+
224
+ .. autoclass:: regstack.email.console.ConsoleEmailService
225
+ :members:
226
+
227
+ .. autoclass:: regstack.email.composer.MailComposer
228
+ :members:
229
+
230
+ .. autofunction:: regstack.email.factory.build_email_service
231
+ ```
232
+
233
+ ### SMS
234
+
235
+ ```{eval-rst}
236
+ .. autoclass:: regstack.sms.base.SmsMessage
237
+ :members:
238
+
239
+ .. autoclass:: regstack.sms.base.SmsService
240
+ :members:
241
+
242
+ .. autofunction:: regstack.sms.base.is_valid_e164
243
+
244
+ .. autoclass:: regstack.sms.null.NullSmsService
245
+ :members:
246
+
247
+ .. autofunction:: regstack.sms.factory.build_sms_service
248
+ ```
249
+
250
+ ## Hooks
251
+
252
+ The event bus regstack uses to fire side-effect notifications
253
+ (`user_registered`, `password_changed`, etc.) without coupling auth
254
+ code to host concerns like CRMs or analytics. See the
255
+ [Embedding guide](embedding.md#subscribing-to-events) for examples.
256
+
257
+ ```{eval-rst}
258
+ .. autoclass:: regstack.hooks.events.HookRegistry
259
+ :members:
260
+
261
+ .. autodata:: regstack.hooks.events.KNOWN_EVENTS
262
+ ```
263
+
264
+ ## Routers
265
+
266
+ Hosts normally access these via the `regstack.router` and
267
+ `regstack.ui_router` properties; the builder functions are public for
268
+ hosts that want to compose differently.
269
+
270
+ ```{eval-rst}
271
+ .. autofunction:: regstack.routers.build_router
272
+
273
+ .. autofunction:: regstack.ui.pages.build_ui_router
274
+
275
+ .. autofunction:: regstack.ui.pages.build_ui_environment
276
+
277
+ .. autofunction:: regstack.ui.pages.default_static_dir
278
+ ```
@@ -72,7 +72,6 @@ The façade exposes:
72
72
  - `backend` — the active `regstack.backends.base.Backend`.
73
73
  - `install_schema()` — install indexes (Mongo) or run
74
74
  [Alembic](https://alembic.sqlalchemy.org/) migrations (SQL).
75
- `install_indexes()` is kept as a back-compat alias.
76
75
  - `aclose()` — tear down the backend's connection pool.
77
76
  - `bootstrap_admin(email, password)`,
78
77
  `add_template_dir(path)`, `set_email_backend(...)`,
@@ -3,6 +3,67 @@
3
3
  All notable changes to this project are documented here. Versions follow
4
4
  [Semantic Versioning](https://semver.org/) once `1.0.0` ships.
5
5
 
6
+ ## 0.2.4 — 2026-04-28
7
+
8
+ **Breaking** — every back-compat shim left over from the
9
+ multi-backend refactor has been removed.
10
+
11
+ ### Removed
12
+
13
+ - `RegStack.install_indexes()` — the 0.1.x alias for
14
+ `install_schema()`. Call `install_schema()`.
15
+ - `ObjectIdStr` alias for `IdStr` in `regstack.models._objectid`.
16
+ Import `IdStr` directly.
17
+ - `__all__`-based re-exports of `UserAlreadyExistsError`,
18
+ `PendingAlreadyExistsError`, `MfaVerifyOutcome`, and
19
+ `MfaVerifyResult` from `regstack.backends.mongo.repositories.*` and
20
+ the package `__init__`. Their canonical home is
21
+ `regstack.backends.protocols`; that's where every consumer in the
22
+ package itself already imports them.
23
+
24
+ ### Migration
25
+
26
+ | Old | New |
27
+ |----------------------------------------------------------------------------------|----------------------------------------------------------------|
28
+ | `await regstack.install_indexes()` | `await regstack.install_schema()` |
29
+ | `from regstack.models._objectid import ObjectIdStr` | `from regstack.models._objectid import IdStr` |
30
+ | `from regstack.backends.mongo.repositories.user_repo import UserAlreadyExistsError` | `from regstack.backends.protocols import UserAlreadyExistsError` |
31
+ | `from regstack.backends.mongo.repositories.pending_repo import PendingAlreadyExistsError` | `from regstack.backends.protocols import PendingAlreadyExistsError` |
32
+ | `from regstack.backends.mongo.repositories.mfa_code_repo import MfaVerifyOutcome, MfaVerifyResult` | `from regstack.backends.protocols import MfaVerifyOutcome, MfaVerifyResult` |
33
+
34
+ The internal Mongo helper
35
+ `regstack.backends.mongo.indexes.install_indexes(db, config)` is
36
+ unchanged — that's the function `MongoBackend.install_schema` calls
37
+ to actually create the indexes.
38
+
39
+ ## 0.2.3 — 2026-04-28
40
+
41
+ **Docs-only release.** API reference rewritten around the current
42
+ package layout, public surface gained proper Google-style docstrings.
43
+
44
+ ### Changed
45
+
46
+ - ``docs/api.md`` restructured around the post-multi-backend package
47
+ layout (``regstack.backends.{base,protocols,factory,mongo,sql}`` and
48
+ friends). Each section now opens with a one-paragraph orientation
49
+ before the autodoc directives. The pre-refactor
50
+ ``regstack.db.repositories.*`` references that rendered empty are
51
+ gone.
52
+ - Added Google-style docstrings (purpose summary + Args / Returns /
53
+ Raises) to the most-touched public methods on ``RegStack``,
54
+ ``JwtCodec``, ``PasswordHasher``, ``LockoutService``,
55
+ ``AuthDependencies``, ``HookRegistry``, ``EmailService``,
56
+ ``SmsService``, ``build_router``, ``build_ui_router``,
57
+ ``build_ui_environment``, ``default_static_dir``, ``Clock`` /
58
+ ``SystemClock`` / ``FrozenClock``.
59
+ - Dataclass field documentation moved to PEP 258 attribute docstrings
60
+ on ``TokenPayload``, ``LockoutDecision``, ``EmailMessage``,
61
+ ``SmsMessage``, ``MfaVerifyResult`` — autodoc now renders each field
62
+ with its description without the "duplicate object description"
63
+ warnings the napoleon ``Attributes:`` block was triggering.
64
+ - ``MfaVerifyOutcome`` enum docstring reformatted as a bullet list
65
+ (the napoleon ``Members:`` block isn't a recognised section).
66
+
6
67
  ## 0.2.2 — 2026-04-28
7
68
 
8
69
  **Docs-only release.**
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "regstack"
3
- version = "0.2.2"
3
+ version = "0.2.4"
4
4
  description = "Embeddable user registration, login, and account management for FastAPI apps. SQLite / Postgres / MongoDB."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"