persistence-kit 3.0.2__tar.gz → 3.3.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 (69) hide show
  1. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/PKG-INFO +141 -5
  2. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/README.md +128 -2
  3. persistence_kit-3.3.0/persistence_kit/__init__.py +233 -0
  4. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/api/__init__.py +3 -0
  5. persistence_kit-3.3.0/persistence_kit/api/rate_limit.py +103 -0
  6. persistence_kit-3.3.0/persistence_kit/authenticated_user.py +37 -0
  7. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/sqlalchemy_repo/sqlalchemy_engine.py +1 -1
  8. persistence_kit-3.3.0/persistence_kit/security/__init__.py +82 -0
  9. persistence_kit-3.3.0/persistence_kit/security/factory.py +156 -0
  10. persistence_kit-3.3.0/persistence_kit/security/ports.py +123 -0
  11. persistence_kit-3.3.0/persistence_kit/security/providers/__init__.py +23 -0
  12. persistence_kit-3.3.0/persistence_kit/security/providers/cognito_identity_provider.py +1232 -0
  13. persistence_kit-3.3.0/persistence_kit/security/providers/memory_security_provider.py +570 -0
  14. persistence_kit-3.3.0/persistence_kit/security/registration.py +100 -0
  15. persistence_kit-3.3.0/persistence_kit/security/token_verifiers/__init__.py +23 -0
  16. persistence_kit-3.3.0/persistence_kit/security/token_verifiers/cognito_jwt_verifier.py +60 -0
  17. persistence_kit-3.3.0/persistence_kit/security/token_verifiers/memory_jwt_verifier.py +44 -0
  18. persistence_kit-3.3.0/persistence_kit/settings/__init__.py +29 -0
  19. persistence_kit-3.3.0/persistence_kit/settings/app_settings.py +125 -0
  20. persistence_kit-3.3.0/persistence_kit/storage/__init__.py +80 -0
  21. persistence_kit-3.3.0/persistence_kit/storage/contracts.py +30 -0
  22. persistence_kit-3.3.0/persistence_kit/storage/errors.py +18 -0
  23. persistence_kit-3.3.0/persistence_kit/storage/factory.py +140 -0
  24. persistence_kit-3.3.0/persistence_kit/storage/local.py +148 -0
  25. persistence_kit-3.3.0/persistence_kit/storage/media.py +107 -0
  26. persistence_kit-3.3.0/persistence_kit/storage/routes.py +119 -0
  27. persistence_kit-3.3.0/persistence_kit/storage/s3.py +125 -0
  28. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/pyproject.toml +15 -3
  29. persistence_kit-3.0.2/persistence_kit/__init__.py +0 -46
  30. persistence_kit-3.0.2/persistence_kit/settings/__init__.py +0 -5
  31. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/LICENSE +0 -0
  32. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/api/common.py +0 -0
  33. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/api/error_handlers.py +0 -0
  34. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/api/exceptions.py +0 -0
  35. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/api/route_loader.py +0 -0
  36. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/bootstrap/__init__.py +0 -0
  37. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/bootstrap/configuration.py +0 -0
  38. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/bootstrap/seeders.py +0 -0
  39. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/bootstrap/startup.py +0 -0
  40. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/contracts/__init__.py +0 -0
  41. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/contracts/repository.py +0 -0
  42. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/contracts/view_repository.py +0 -0
  43. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/py.typed +0 -0
  44. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/__init__.py +0 -0
  45. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/dynamodb_repo/dynamodb_mapper.py +0 -0
  46. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/dynamodb_repo/dynamodb_repo.py +0 -0
  47. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/filter_ops.py +0 -0
  48. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/memory_repo/__init__.py +0 -0
  49. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/memory_repo/memory_repo.py +0 -0
  50. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/mongo_repo/__init__.py +0 -0
  51. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/mongo_repo/mongo_mapper.py +0 -0
  52. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/mongo_repo/mongo_repo.py +0 -0
  53. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/sqlalchemy_repo/__init__.py +0 -0
  54. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/sqlalchemy_repo/schema_evolve.py +0 -0
  55. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/sqlalchemy_repo/sqlalchemy_dataclass_mapper.py +0 -0
  56. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/sqlalchemy_repo/sqlalchemy_repo.py +0 -0
  57. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository/sqlalchemy_repo/table_factory.py +0 -0
  58. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository_factory/__init__.py +0 -0
  59. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository_factory/factory/__init__.py +0 -0
  60. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository_factory/factory/repository_factory.py +0 -0
  61. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository_factory/registry/__init__.py +0 -0
  62. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository_factory/registry/entity_registry.py +0 -0
  63. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository_factory/view/__init__.py +0 -0
  64. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/repository_factory/view/populating_repository.py +0 -0
  65. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/settings/constants.py +0 -0
  66. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/settings/parsers.py +0 -0
  67. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/settings/repo_settings.py +0 -0
  68. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/utils/__init__.py +0 -0
  69. {persistence_kit-3.0.2 → persistence_kit-3.3.0}/persistence_kit/utils/upsert.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: persistence-kit
3
- Version: 3.0.2
3
+ Version: 3.3.0
4
4
  Summary: Reusable persistence and repository toolkit
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -18,11 +18,21 @@ Classifier: Programming Language :: Python :: 3.13
18
18
  Classifier: Programming Language :: Python :: 3.14
19
19
  Classifier: Topic :: Database
20
20
  Classifier: Typing :: Typed
21
+ Provides-Extra: all
22
+ Provides-Extra: api
23
+ Provides-Extra: dynamodb
24
+ Provides-Extra: security
25
+ Provides-Extra: security-cognito
26
+ Provides-Extra: storage-routes
27
+ Provides-Extra: storage-s3
28
+ Provides-Extra: testing
21
29
  Requires-Dist: asyncpg (>=0.30.0,<0.31.0)
22
- Requires-Dist: boto3 (>=1.35.0,<2.0.0)
23
- Requires-Dist: fastapi (>=0.115.0,<0.116.0)
30
+ Requires-Dist: boto3 (>=1.35.0,<2.0.0) ; extra == "storage-s3" or extra == "security-cognito" or extra == "dynamodb" or extra == "all"
31
+ Requires-Dist: fastapi (>=0.115.0,<0.116.0) ; extra == "api" or extra == "storage-routes" or extra == "security" or extra == "security-cognito" or extra == "testing" or extra == "all"
24
32
  Requires-Dist: motor (>=3.7.1,<4.0.0)
25
33
  Requires-Dist: pydantic-settings (>=2.3.0,<3.0.0)
34
+ Requires-Dist: pyjwt[crypto] (>=2.10.1,<3.0.0) ; extra == "security" or extra == "security-cognito" or extra == "testing" or extra == "all"
35
+ Requires-Dist: python-multipart (>=0.0.20,<0.0.21) ; extra == "api" or extra == "storage-routes" or extra == "security" or extra == "security-cognito" or extra == "testing" or extra == "all"
26
36
  Requires-Dist: sqlalchemy[asyncio] (>=2.0.43,<3.0.0)
27
37
  Requires-Dist: typing-extensions (>=4.12.0,<5.0.0)
28
38
  Project-URL: Documentation, https://github.com/andresfserrano/persistence-kit#readme
@@ -53,6 +63,8 @@ Author: Andres Felipe Serrano Barrios
53
63
  - `api/`: reusable API exceptions, handlers, and route loading helpers
54
64
  - `bootstrap/`: startup helpers, configuration registry, and seed orchestration
55
65
  - `utils/`: transversal helpers such as upsert utilities
66
+ - `storage/`: reusable object storage contracts and local/S3 adapters
67
+ - `security/`: reusable identity provider contracts, Cognito/memory adapters, and JWT verifiers
56
68
  - `repository/`: concrete repository implementations by backend
57
69
  - `repository_factory/`: entity registry, repository creation, and populated view repository
58
70
 
@@ -67,6 +79,28 @@ Recommended rule:
67
79
  pip install persistence-kit
68
80
  ```
69
81
 
82
+ The base install keeps optional capabilities out of the dependency graph. Enable
83
+ only what the host project uses:
84
+
85
+ ```bash
86
+ pip install "persistence-kit[api]"
87
+ pip install "persistence-kit[security]"
88
+ pip install "persistence-kit[security-cognito]"
89
+ pip install "persistence-kit[storage-s3]"
90
+ pip install "persistence-kit[storage-routes]"
91
+ pip install "persistence-kit[dynamodb]"
92
+ ```
93
+
94
+ Available capabilities:
95
+
96
+ - `api`: FastAPI exceptions, pagination helpers, route loading, and error handlers.
97
+ - `security`: memory identity provider and JWT verifier.
98
+ - `security-cognito`: security plus Cognito and AWS/JWKS dependencies.
99
+ - `storage-s3`: S3 object storage adapter.
100
+ - `storage-routes`: FastAPI local export download router.
101
+ - `dynamodb`: DynamoDB repository backend.
102
+ - `all`: every optional capability.
103
+
70
104
  ## Quick Start
71
105
 
72
106
  ```python
@@ -96,10 +130,25 @@ from persistence_kit import (
96
130
  Repository,
97
131
  ViewRepository,
98
132
  RepoSettings,
133
+ PersistenceKitSettings,
134
+ AuthProvider,
135
+ ExportStorageProvider,
99
136
  Database,
100
137
  ConfigRegistry,
101
138
  configuration,
102
139
  SeederProvider,
140
+ ObjectStorage,
141
+ LocalObjectStorage,
142
+ S3ObjectStorage,
143
+ get_export_storage,
144
+ build_local_export_storage_router,
145
+ IdentityProvider,
146
+ MemorySecurityProvider,
147
+ CognitoIdentityProvider,
148
+ MemoryJwtVerifier,
149
+ CognitoJwtVerifier,
150
+ get_identity_provider,
151
+ get_token_verifier,
103
152
  build_api_router,
104
153
  handle_service_errors,
105
154
  handle_repository_errors,
@@ -125,6 +174,93 @@ Use internal paths only for implementation details, for example:
125
174
  - `persistence_kit.repository_factory.registry.entity_registry`
126
175
  - `persistence_kit.repository_factory.view.populating_repository`
127
176
 
177
+ ## Object Storage
178
+
179
+ `persistence_kit.storage` provides driven adapters for storing generated files or
180
+ binary objects outside the domain layer:
181
+
182
+ ```python
183
+ from persistence_kit.storage import LocalObjectStorage
184
+
185
+ storage = LocalObjectStorage(
186
+ base_dir=".local",
187
+ public_base_url="http://localhost:8000",
188
+ signing_secret="dev-secret",
189
+ )
190
+
191
+ key = await storage.upload("exports/report.csv", b"id,name\n1,Ada\n", "text/csv")
192
+ url = await storage.generate_presigned_url(key)
193
+ ```
194
+
195
+ Available adapters:
196
+
197
+ - `LocalObjectStorage`: stores files under a configured local directory and signs download URLs.
198
+ - `S3ObjectStorage`: uploads objects to S3 and returns AWS presigned URLs.
199
+
200
+ Backward-compatible aliases are exported for applications that previously used
201
+ `LocalExportStorageProvider` and `S3ExportStorageProvider`.
202
+
203
+ `get_export_storage(settings)` builds and caches the configured adapter from a
204
+ `PersistenceKitSettings` instance or a subclass inherited by the host app.
205
+
206
+ For FastAPI applications, `build_local_export_storage_router(...)` exposes a
207
+ reusable local download route. The host app passes its settings provider,
208
+ optional-current-user dependency, and product authorization callback.
209
+
210
+ Install `persistence-kit[storage-s3]` before using `S3ObjectStorage` and
211
+ `persistence-kit[storage-routes]` before using the FastAPI export route.
212
+
213
+ ## Security
214
+
215
+ `persistence_kit.security` provides reusable driven adapters for application
216
+ authentication flows:
217
+
218
+ ```python
219
+ from persistence_kit.security import MemorySecurityProvider, MemoryJwtVerifier
220
+
221
+ identity = MemorySecurityProvider(
222
+ jwt_secret="dev-secret-with-enough-length",
223
+ jwt_issuer="local-sandbox",
224
+ seed_role_users=True,
225
+ seed_role_codes=("admin", "operator"),
226
+ seed_user_domain="example.org",
227
+ )
228
+ verifier = MemoryJwtVerifier(secret="dev-secret-with-enough-length", issuer="local-sandbox")
229
+ ```
230
+
231
+ Available pieces:
232
+
233
+ - `IdentityProvider` and `TokenVerifier`: application-facing protocols.
234
+ - `MemorySecurityProvider`: local identity provider for tests/sandbox environments.
235
+ - `CognitoIdentityProvider`: AWS Cognito identity provider adapter.
236
+ - `MemoryJwtVerifier` and `CognitoJwtVerifier`: JWT token verifiers.
237
+ - Registration/login/password-reset result dataclasses and helper functions such as `unique_roles`.
238
+
239
+ Host applications should keep domain-specific roles, authorization policies,
240
+ scope rules, and route permission matrices outside the kit.
241
+
242
+ Install `persistence-kit[security]` for the memory provider/JWT verifier and
243
+ `persistence-kit[security-cognito]` for Cognito support.
244
+
245
+ `PersistenceKitSettings` centralizes common auth, storage, observability, AWS,
246
+ and job-service settings. Host applications can inherit from it and override
247
+ only product-specific defaults:
248
+
249
+ ```python
250
+ from persistence_kit import Database, PersistenceKitSettings
251
+
252
+
253
+ class Settings(PersistenceKitSettings):
254
+ service_name: str = "my-api"
255
+ key_status_history_database: Database = Database.MONGO
256
+ memory_seed_role_codes: tuple[str, ...] = ("admin", "operator")
257
+ ```
258
+
259
+ `persistence_kit.security.factory` can build the identity provider and token
260
+ verifier from that inherited settings object. `persistence_kit.storage.factory`
261
+ does the same for export storage, and `persistence_kit.storage.routes` exposes
262
+ the reusable FastAPI local export route.
263
+
128
264
  ## Typical Host Application Flow
129
265
 
130
266
  1. Define your entities as dataclasses.
@@ -150,13 +286,13 @@ Create the local environment and run tests from the library root:
150
286
 
151
287
  ```bash
152
288
  poetry lock
153
- poetry install --with dev
289
+ poetry install --with dev --all-extras
154
290
  poetry run pytest -q
155
291
  ```
156
292
 
157
293
  Current validation baseline:
158
294
 
159
- - `persistence_kit`: `138 passed`
295
+ - `persistence_kit`: `335 passed`
160
296
 
161
297
  ## Publish to PyPI (Manual)
162
298
 
@@ -21,6 +21,8 @@ Author: Andres Felipe Serrano Barrios
21
21
  - `api/`: reusable API exceptions, handlers, and route loading helpers
22
22
  - `bootstrap/`: startup helpers, configuration registry, and seed orchestration
23
23
  - `utils/`: transversal helpers such as upsert utilities
24
+ - `storage/`: reusable object storage contracts and local/S3 adapters
25
+ - `security/`: reusable identity provider contracts, Cognito/memory adapters, and JWT verifiers
24
26
  - `repository/`: concrete repository implementations by backend
25
27
  - `repository_factory/`: entity registry, repository creation, and populated view repository
26
28
 
@@ -35,6 +37,28 @@ Recommended rule:
35
37
  pip install persistence-kit
36
38
  ```
37
39
 
40
+ The base install keeps optional capabilities out of the dependency graph. Enable
41
+ only what the host project uses:
42
+
43
+ ```bash
44
+ pip install "persistence-kit[api]"
45
+ pip install "persistence-kit[security]"
46
+ pip install "persistence-kit[security-cognito]"
47
+ pip install "persistence-kit[storage-s3]"
48
+ pip install "persistence-kit[storage-routes]"
49
+ pip install "persistence-kit[dynamodb]"
50
+ ```
51
+
52
+ Available capabilities:
53
+
54
+ - `api`: FastAPI exceptions, pagination helpers, route loading, and error handlers.
55
+ - `security`: memory identity provider and JWT verifier.
56
+ - `security-cognito`: security plus Cognito and AWS/JWKS dependencies.
57
+ - `storage-s3`: S3 object storage adapter.
58
+ - `storage-routes`: FastAPI local export download router.
59
+ - `dynamodb`: DynamoDB repository backend.
60
+ - `all`: every optional capability.
61
+
38
62
  ## Quick Start
39
63
 
40
64
  ```python
@@ -64,10 +88,25 @@ from persistence_kit import (
64
88
  Repository,
65
89
  ViewRepository,
66
90
  RepoSettings,
91
+ PersistenceKitSettings,
92
+ AuthProvider,
93
+ ExportStorageProvider,
67
94
  Database,
68
95
  ConfigRegistry,
69
96
  configuration,
70
97
  SeederProvider,
98
+ ObjectStorage,
99
+ LocalObjectStorage,
100
+ S3ObjectStorage,
101
+ get_export_storage,
102
+ build_local_export_storage_router,
103
+ IdentityProvider,
104
+ MemorySecurityProvider,
105
+ CognitoIdentityProvider,
106
+ MemoryJwtVerifier,
107
+ CognitoJwtVerifier,
108
+ get_identity_provider,
109
+ get_token_verifier,
71
110
  build_api_router,
72
111
  handle_service_errors,
73
112
  handle_repository_errors,
@@ -93,6 +132,93 @@ Use internal paths only for implementation details, for example:
93
132
  - `persistence_kit.repository_factory.registry.entity_registry`
94
133
  - `persistence_kit.repository_factory.view.populating_repository`
95
134
 
135
+ ## Object Storage
136
+
137
+ `persistence_kit.storage` provides driven adapters for storing generated files or
138
+ binary objects outside the domain layer:
139
+
140
+ ```python
141
+ from persistence_kit.storage import LocalObjectStorage
142
+
143
+ storage = LocalObjectStorage(
144
+ base_dir=".local",
145
+ public_base_url="http://localhost:8000",
146
+ signing_secret="dev-secret",
147
+ )
148
+
149
+ key = await storage.upload("exports/report.csv", b"id,name\n1,Ada\n", "text/csv")
150
+ url = await storage.generate_presigned_url(key)
151
+ ```
152
+
153
+ Available adapters:
154
+
155
+ - `LocalObjectStorage`: stores files under a configured local directory and signs download URLs.
156
+ - `S3ObjectStorage`: uploads objects to S3 and returns AWS presigned URLs.
157
+
158
+ Backward-compatible aliases are exported for applications that previously used
159
+ `LocalExportStorageProvider` and `S3ExportStorageProvider`.
160
+
161
+ `get_export_storage(settings)` builds and caches the configured adapter from a
162
+ `PersistenceKitSettings` instance or a subclass inherited by the host app.
163
+
164
+ For FastAPI applications, `build_local_export_storage_router(...)` exposes a
165
+ reusable local download route. The host app passes its settings provider,
166
+ optional-current-user dependency, and product authorization callback.
167
+
168
+ Install `persistence-kit[storage-s3]` before using `S3ObjectStorage` and
169
+ `persistence-kit[storage-routes]` before using the FastAPI export route.
170
+
171
+ ## Security
172
+
173
+ `persistence_kit.security` provides reusable driven adapters for application
174
+ authentication flows:
175
+
176
+ ```python
177
+ from persistence_kit.security import MemorySecurityProvider, MemoryJwtVerifier
178
+
179
+ identity = MemorySecurityProvider(
180
+ jwt_secret="dev-secret-with-enough-length",
181
+ jwt_issuer="local-sandbox",
182
+ seed_role_users=True,
183
+ seed_role_codes=("admin", "operator"),
184
+ seed_user_domain="example.org",
185
+ )
186
+ verifier = MemoryJwtVerifier(secret="dev-secret-with-enough-length", issuer="local-sandbox")
187
+ ```
188
+
189
+ Available pieces:
190
+
191
+ - `IdentityProvider` and `TokenVerifier`: application-facing protocols.
192
+ - `MemorySecurityProvider`: local identity provider for tests/sandbox environments.
193
+ - `CognitoIdentityProvider`: AWS Cognito identity provider adapter.
194
+ - `MemoryJwtVerifier` and `CognitoJwtVerifier`: JWT token verifiers.
195
+ - Registration/login/password-reset result dataclasses and helper functions such as `unique_roles`.
196
+
197
+ Host applications should keep domain-specific roles, authorization policies,
198
+ scope rules, and route permission matrices outside the kit.
199
+
200
+ Install `persistence-kit[security]` for the memory provider/JWT verifier and
201
+ `persistence-kit[security-cognito]` for Cognito support.
202
+
203
+ `PersistenceKitSettings` centralizes common auth, storage, observability, AWS,
204
+ and job-service settings. Host applications can inherit from it and override
205
+ only product-specific defaults:
206
+
207
+ ```python
208
+ from persistence_kit import Database, PersistenceKitSettings
209
+
210
+
211
+ class Settings(PersistenceKitSettings):
212
+ service_name: str = "my-api"
213
+ key_status_history_database: Database = Database.MONGO
214
+ memory_seed_role_codes: tuple[str, ...] = ("admin", "operator")
215
+ ```
216
+
217
+ `persistence_kit.security.factory` can build the identity provider and token
218
+ verifier from that inherited settings object. `persistence_kit.storage.factory`
219
+ does the same for export storage, and `persistence_kit.storage.routes` exposes
220
+ the reusable FastAPI local export route.
221
+
96
222
  ## Typical Host Application Flow
97
223
 
98
224
  1. Define your entities as dataclasses.
@@ -118,13 +244,13 @@ Create the local environment and run tests from the library root:
118
244
 
119
245
  ```bash
120
246
  poetry lock
121
- poetry install --with dev
247
+ poetry install --with dev --all-extras
122
248
  poetry run pytest -q
123
249
  ```
124
250
 
125
251
  Current validation baseline:
126
252
 
127
- - `persistence_kit`: `138 passed`
253
+ - `persistence_kit`: `335 passed`
128
254
 
129
255
  ## Publish to PyPI (Manual)
130
256
 
@@ -0,0 +1,233 @@
1
+ from importlib import import_module
2
+
3
+ from .bootstrap.configuration import ConfigRegistry, configuration, set_config_package
4
+ from .bootstrap.seeders import Seeder, SeederProvider
5
+ from .bootstrap.startup import is_duplicate_startup_error, run_startup_bootstrap
6
+ from .contracts.repository import Repository
7
+ from .contracts.view_repository import ViewRepository
8
+ from .settings import (
9
+ DEFAULT_MEMORY_JWT_ISSUER,
10
+ DEFAULT_MEMORY_JWT_SECRET,
11
+ DEFAULT_MEMORY_JWT_TTL_SECONDS,
12
+ LOCAL_DEFAULT_JOB_SERVICE_API_KEY,
13
+ AuthProvider,
14
+ DeploymentStage,
15
+ ExportStorageProvider,
16
+ MediaStorageProvider,
17
+ PersistenceKitSettings,
18
+ )
19
+ from .settings.constants import Database
20
+ from .settings.parsers import split_csv_list
21
+ from .settings.repo_settings import RepoSettings
22
+ from .storage import (
23
+ EXPORT_STORAGE_BUILDERS,
24
+ ExportStorage,
25
+ ExportStorageBuilder,
26
+ ObjectStorage,
27
+ StorageConfigError,
28
+ StorageError,
29
+ StoragePathError,
30
+ StoragePresignError,
31
+ StorageUploadError,
32
+ get_export_storage,
33
+ )
34
+ from .authenticated_user import AuthenticatedUser
35
+ from .utils.upsert import dataclass_field_names, upsert_entity
36
+
37
+ _OPTIONAL_EXPORTS = {
38
+ "ApiError": ("persistence_kit.api.common", "ApiError", "api"),
39
+ "pagination_params": ("persistence_kit.api.common", "pagination_params", "api"),
40
+ "BaseAPIException": ("persistence_kit.api.exceptions", "BaseAPIException", "api"),
41
+ "NotFoundException": ("persistence_kit.api.exceptions", "NotFoundException", "api"),
42
+ "ValidationException": ("persistence_kit.api.exceptions", "ValidationException", "api"),
43
+ "BusinessRuleException": (
44
+ "persistence_kit.api.exceptions",
45
+ "BusinessRuleException",
46
+ "api",
47
+ ),
48
+ "DatabaseException": ("persistence_kit.api.exceptions", "DatabaseException", "api"),
49
+ "handle_service_errors": (
50
+ "persistence_kit.api.error_handlers",
51
+ "handle_service_errors",
52
+ "api",
53
+ ),
54
+ "handle_repository_errors": (
55
+ "persistence_kit.api.error_handlers",
56
+ "handle_repository_errors",
57
+ "api",
58
+ ),
59
+ "build_api_router": ("persistence_kit.api.route_loader", "build_api_router", "api"),
60
+ "InMemoryRateLimiter": ("persistence_kit.api.rate_limit", "InMemoryRateLimiter", "api"),
61
+ "build_auth_rate_limit_dependency": (
62
+ "persistence_kit.api.rate_limit",
63
+ "build_auth_rate_limit_dependency",
64
+ "api",
65
+ ),
66
+ "IdentityProvider": ("persistence_kit.security.ports", "IdentityProvider", "security"),
67
+ "TokenVerifier": ("persistence_kit.security.ports", "TokenVerifier", "security"),
68
+ "CognitoIdentityProvider": (
69
+ "persistence_kit.security.providers",
70
+ "CognitoIdentityProvider",
71
+ "security-cognito",
72
+ ),
73
+ "MemorySecurityProvider": (
74
+ "persistence_kit.security.providers",
75
+ "MemorySecurityProvider",
76
+ "testing",
77
+ ),
78
+ "CognitoJwtVerifier": (
79
+ "persistence_kit.security.token_verifiers",
80
+ "CognitoJwtVerifier",
81
+ "security-cognito",
82
+ ),
83
+ "MemoryJwtVerifier": (
84
+ "persistence_kit.security.token_verifiers",
85
+ "MemoryJwtVerifier",
86
+ "testing",
87
+ ),
88
+ "get_identity_provider": (
89
+ "persistence_kit.security.factory",
90
+ "get_identity_provider",
91
+ "security",
92
+ ),
93
+ "get_token_verifier": (
94
+ "persistence_kit.security.factory",
95
+ "get_token_verifier",
96
+ "security",
97
+ ),
98
+ "RegistrationResult": (
99
+ "persistence_kit.security.registration",
100
+ "RegistrationResult",
101
+ "security",
102
+ ),
103
+ "RoleAssignmentResult": (
104
+ "persistence_kit.security.registration",
105
+ "RoleAssignmentResult",
106
+ "security",
107
+ ),
108
+ "UserStatusUpdateResult": (
109
+ "persistence_kit.security.registration",
110
+ "UserStatusUpdateResult",
111
+ "security",
112
+ ),
113
+ "LoginResult": ("persistence_kit.security.registration", "LoginResult", "security"),
114
+ "RefreshTokensResult": (
115
+ "persistence_kit.security.registration",
116
+ "RefreshTokensResult",
117
+ "security",
118
+ ),
119
+ "LogoutResult": ("persistence_kit.security.registration", "LogoutResult", "security"),
120
+ "PasswordResetCodeRequestResult": (
121
+ "persistence_kit.security.registration",
122
+ "PasswordResetCodeRequestResult",
123
+ "security",
124
+ ),
125
+ "PasswordResetConfirmResult": (
126
+ "persistence_kit.security.registration",
127
+ "PasswordResetConfirmResult",
128
+ "security",
129
+ ),
130
+ "PasswordResetResult": (
131
+ "persistence_kit.security.registration",
132
+ "PasswordResetResult",
133
+ "security",
134
+ ),
135
+ "RegisteredUserResult": (
136
+ "persistence_kit.security.registration",
137
+ "RegisteredUserResult",
138
+ "security",
139
+ ),
140
+ "RegisteredUsersPageResult": (
141
+ "persistence_kit.security.registration",
142
+ "RegisteredUsersPageResult",
143
+ "security",
144
+ ),
145
+ "validate_allowed_email_domain": (
146
+ "persistence_kit.security.registration",
147
+ "validate_allowed_email_domain",
148
+ "security",
149
+ ),
150
+ "unique_roles": ("persistence_kit.security.registration", "unique_roles", "security"),
151
+ "LocalObjectStorage": ("persistence_kit.storage.local", "LocalObjectStorage", "testing"),
152
+ "LocalExportStorageProvider": (
153
+ "persistence_kit.storage.local",
154
+ "LocalExportStorageProvider",
155
+ "testing",
156
+ ),
157
+ "S3ObjectStorage": ("persistence_kit.storage.s3", "S3ObjectStorage", "storage-s3"),
158
+ "S3ExportStorageProvider": (
159
+ "persistence_kit.storage.s3",
160
+ "S3ExportStorageProvider",
161
+ "storage-s3",
162
+ ),
163
+ "build_local_export_storage_router": (
164
+ "persistence_kit.storage.routes",
165
+ "build_local_export_storage_router",
166
+ "storage-routes",
167
+ ),
168
+ "serve_local_export": (
169
+ "persistence_kit.storage.routes",
170
+ "serve_local_export",
171
+ "storage-routes",
172
+ ),
173
+ "guess_export_media_type": (
174
+ "persistence_kit.storage.routes",
175
+ "guess_export_media_type",
176
+ "storage-routes",
177
+ ),
178
+ }
179
+
180
+ __all__ = [
181
+ "Repository",
182
+ "ViewRepository",
183
+ "split_csv_list",
184
+ "ConfigRegistry",
185
+ "configuration",
186
+ "Database",
187
+ "RepoSettings",
188
+ "AuthProvider",
189
+ "ExportStorageProvider",
190
+ "MediaStorageProvider",
191
+ "DeploymentStage",
192
+ "LOCAL_DEFAULT_JOB_SERVICE_API_KEY",
193
+ "DEFAULT_MEMORY_JWT_SECRET",
194
+ "DEFAULT_MEMORY_JWT_ISSUER",
195
+ "DEFAULT_MEMORY_JWT_TTL_SECONDS",
196
+ "PersistenceKitSettings",
197
+ "Seeder",
198
+ "SeederProvider",
199
+ "set_config_package",
200
+ "is_duplicate_startup_error",
201
+ "run_startup_bootstrap",
202
+ "AuthenticatedUser",
203
+ "dataclass_field_names",
204
+ "upsert_entity",
205
+ "ObjectStorage",
206
+ "StorageError",
207
+ "StorageConfigError",
208
+ "StoragePathError",
209
+ "StorageUploadError",
210
+ "StoragePresignError",
211
+ "ExportStorage",
212
+ "ExportStorageBuilder",
213
+ "EXPORT_STORAGE_BUILDERS",
214
+ "get_export_storage",
215
+ *_OPTIONAL_EXPORTS,
216
+ ]
217
+
218
+
219
+ def __getattr__(name: str):
220
+ if name not in _OPTIONAL_EXPORTS:
221
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
222
+
223
+ module_name, attr_name, extra_name = _OPTIONAL_EXPORTS[name]
224
+ try:
225
+ module = import_module(module_name)
226
+ except ModuleNotFoundError as exc:
227
+ raise ModuleNotFoundError(
228
+ f"{name} requiere la capability opcional '{extra_name}'. "
229
+ f"Instala con `persistence-kit[{extra_name}]`."
230
+ ) from exc
231
+ value = getattr(module, attr_name)
232
+ globals()[name] = value
233
+ return value
@@ -7,6 +7,7 @@ from .exceptions import (
7
7
  NotFoundException,
8
8
  ValidationException,
9
9
  )
10
+ from .rate_limit import InMemoryRateLimiter, build_auth_rate_limit_dependency
10
11
  from .route_loader import build_api_router
11
12
 
12
13
  __all__ = [
@@ -20,4 +21,6 @@ __all__ = [
20
21
  "handle_service_errors",
21
22
  "handle_repository_errors",
22
23
  "build_api_router",
24
+ "InMemoryRateLimiter",
25
+ "build_auth_rate_limit_dependency",
23
26
  ]