mdb-engine 0.2.0__py3-none-any.whl → 0.2.3__py3-none-any.whl

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 (66) hide show
  1. mdb_engine/__init__.py +1 -1
  2. mdb_engine/auth/audit.py +40 -40
  3. mdb_engine/auth/base.py +3 -3
  4. mdb_engine/auth/casbin_factory.py +6 -6
  5. mdb_engine/auth/config_defaults.py +5 -5
  6. mdb_engine/auth/config_helpers.py +12 -12
  7. mdb_engine/auth/cookie_utils.py +9 -9
  8. mdb_engine/auth/csrf.py +9 -8
  9. mdb_engine/auth/decorators.py +7 -6
  10. mdb_engine/auth/dependencies.py +22 -21
  11. mdb_engine/auth/integration.py +9 -9
  12. mdb_engine/auth/jwt.py +9 -9
  13. mdb_engine/auth/middleware.py +4 -3
  14. mdb_engine/auth/oso_factory.py +6 -6
  15. mdb_engine/auth/provider.py +4 -4
  16. mdb_engine/auth/rate_limiter.py +12 -11
  17. mdb_engine/auth/restrictions.py +16 -15
  18. mdb_engine/auth/session_manager.py +11 -13
  19. mdb_engine/auth/shared_middleware.py +16 -15
  20. mdb_engine/auth/shared_users.py +20 -20
  21. mdb_engine/auth/token_lifecycle.py +10 -12
  22. mdb_engine/auth/token_store.py +4 -5
  23. mdb_engine/auth/users.py +51 -52
  24. mdb_engine/auth/utils.py +29 -33
  25. mdb_engine/cli/commands/generate.py +6 -6
  26. mdb_engine/cli/utils.py +4 -4
  27. mdb_engine/config.py +6 -7
  28. mdb_engine/core/app_registration.py +12 -12
  29. mdb_engine/core/app_secrets.py +1 -2
  30. mdb_engine/core/connection.py +3 -4
  31. mdb_engine/core/encryption.py +1 -2
  32. mdb_engine/core/engine.py +43 -44
  33. mdb_engine/core/manifest.py +59 -58
  34. mdb_engine/core/ray_integration.py +10 -9
  35. mdb_engine/core/seeding.py +3 -3
  36. mdb_engine/core/service_initialization.py +10 -9
  37. mdb_engine/core/types.py +40 -40
  38. mdb_engine/database/abstraction.py +15 -16
  39. mdb_engine/database/connection.py +40 -12
  40. mdb_engine/database/query_validator.py +8 -8
  41. mdb_engine/database/resource_limiter.py +7 -7
  42. mdb_engine/database/scoped_wrapper.py +51 -58
  43. mdb_engine/dependencies.py +14 -13
  44. mdb_engine/di/container.py +12 -13
  45. mdb_engine/di/providers.py +14 -13
  46. mdb_engine/di/scopes.py +5 -5
  47. mdb_engine/embeddings/dependencies.py +2 -2
  48. mdb_engine/embeddings/service.py +31 -43
  49. mdb_engine/exceptions.py +20 -20
  50. mdb_engine/indexes/helpers.py +11 -11
  51. mdb_engine/indexes/manager.py +9 -9
  52. mdb_engine/memory/service.py +30 -30
  53. mdb_engine/observability/health.py +10 -9
  54. mdb_engine/observability/logging.py +10 -10
  55. mdb_engine/observability/metrics.py +8 -7
  56. mdb_engine/repositories/base.py +25 -25
  57. mdb_engine/repositories/mongo.py +17 -17
  58. mdb_engine/repositories/unit_of_work.py +6 -6
  59. mdb_engine/routing/websockets.py +19 -18
  60. {mdb_engine-0.2.0.dist-info → mdb_engine-0.2.3.dist-info}/METADATA +8 -8
  61. mdb_engine-0.2.3.dist-info/RECORD +96 -0
  62. mdb_engine-0.2.0.dist-info/RECORD +0 -96
  63. {mdb_engine-0.2.0.dist-info → mdb_engine-0.2.3.dist-info}/WHEEL +0 -0
  64. {mdb_engine-0.2.0.dist-info → mdb_engine-0.2.3.dist-info}/entry_points.txt +0 -0
  65. {mdb_engine-0.2.0.dist-info → mdb_engine-0.2.3.dist-info}/licenses/LICENSE +0 -0
  66. {mdb_engine-0.2.0.dist-info → mdb_engine-0.2.3.dist-info}/top_level.txt +0 -0
mdb_engine/auth/utils.py CHANGED
@@ -11,7 +11,7 @@ import logging
11
11
  import re
12
12
  import uuid
13
13
  from datetime import datetime
14
- from typing import Any, Dict, List, Optional, Tuple
14
+ from typing import Any
15
15
 
16
16
  import bcrypt
17
17
  from fastapi import Request, Response
@@ -43,7 +43,7 @@ def _detect_browser(user_agent: str) -> str:
43
43
  return "unknown"
44
44
 
45
45
 
46
- def _detect_os_and_device_type(user_agent: str) -> Tuple[str, str]:
46
+ def _detect_os_and_device_type(user_agent: str) -> tuple[str, str]:
47
47
  """Detect OS and device type from user agent string."""
48
48
  if not user_agent:
49
49
  return "unknown", "desktop"
@@ -64,7 +64,7 @@ def _detect_os_and_device_type(user_agent: str) -> Tuple[str, str]:
64
64
  return "unknown", "desktop"
65
65
 
66
66
 
67
- def get_device_info(request: Request) -> Dict[str, Any]:
67
+ def get_device_info(request: Request) -> dict[str, Any]:
68
68
  """
69
69
  Extract device information from request.
70
70
 
@@ -236,15 +236,15 @@ async def check_password_breach(password: str) -> bool:
236
236
 
237
237
  def validate_password_strength(
238
238
  password: str,
239
- min_length: Optional[int] = None,
240
- require_uppercase: Optional[bool] = None,
241
- require_lowercase: Optional[bool] = None,
242
- require_numbers: Optional[bool] = None,
243
- require_special: Optional[bool] = None,
244
- min_entropy_bits: Optional[int] = None,
245
- check_common_passwords: Optional[bool] = None,
246
- config: Optional[Dict[str, Any]] = None,
247
- ) -> Tuple[bool, List[str]]:
239
+ min_length: int | None = None,
240
+ require_uppercase: bool | None = None,
241
+ require_lowercase: bool | None = None,
242
+ require_numbers: bool | None = None,
243
+ require_special: bool | None = None,
244
+ min_entropy_bits: int | None = None,
245
+ check_common_passwords: bool | None = None,
246
+ config: dict[str, Any] | None = None,
247
+ ) -> tuple[bool, list[str]]:
248
248
  """
249
249
  Validate password strength with configurable rules.
250
250
 
@@ -338,9 +338,9 @@ def validate_password_strength(
338
338
 
339
339
  async def validate_password_strength_async(
340
340
  password: str,
341
- config: Optional[Dict[str, Any]] = None,
342
- check_breaches: Optional[bool] = None,
343
- ) -> Tuple[bool, List[str]]:
341
+ config: dict[str, Any] | None = None,
342
+ check_breaches: bool | None = None,
343
+ ) -> tuple[bool, list[str]]:
344
344
  """
345
345
  Async version of validate_password_strength with breach checking.
346
346
 
@@ -404,10 +404,10 @@ async def login_user(
404
404
  email: str,
405
405
  password: str,
406
406
  db,
407
- config: Optional[Dict[str, Any]] = None,
407
+ config: dict[str, Any] | None = None,
408
408
  remember_me: bool = False,
409
- redirect_url: Optional[str] = None,
410
- ) -> Dict[str, Any]:
409
+ redirect_url: str | None = None,
410
+ ) -> dict[str, Any]:
411
411
  """
412
412
  Handle user login with automatic token generation and cookie setting.
413
413
 
@@ -571,8 +571,8 @@ def _validate_email_format(email: str) -> bool:
571
571
 
572
572
 
573
573
  def _get_password_policy_from_config(
574
- request: Request, config: Optional[Dict[str, Any]]
575
- ) -> Optional[Dict[str, Any]]:
574
+ request: Request, config: dict[str, Any] | None
575
+ ) -> dict[str, Any] | None:
576
576
  """Get password policy from config or request."""
577
577
  if config:
578
578
  security = config.get("security", {})
@@ -585,8 +585,8 @@ def _get_password_policy_from_config(
585
585
 
586
586
 
587
587
  async def _create_user_document(
588
- email: str, password: str, extra_data: Optional[Dict[str, Any]]
589
- ) -> Dict[str, Any]:
588
+ email: str, password: str, extra_data: dict[str, Any] | None
589
+ ) -> dict[str, Any]:
590
590
  """Create user document with hashed password."""
591
591
  password_hash = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())
592
592
  user_doc = {
@@ -600,9 +600,7 @@ async def _create_user_document(
600
600
  return user_doc
601
601
 
602
602
 
603
- def _create_registration_response(
604
- user_doc: Dict[str, Any], redirect_url: Optional[str]
605
- ) -> Response:
603
+ def _create_registration_response(user_doc: dict[str, Any], redirect_url: str | None) -> Response:
606
604
  """Create response for registration."""
607
605
  if redirect_url:
608
606
  return RedirectResponse(url=redirect_url, status_code=302)
@@ -622,10 +620,10 @@ async def register_user(
622
620
  email: str,
623
621
  password: str,
624
622
  db,
625
- config: Optional[Dict[str, Any]] = None,
626
- extra_data: Optional[Dict[str, Any]] = None,
627
- redirect_url: Optional[str] = None,
628
- ) -> Dict[str, Any]:
623
+ config: dict[str, Any] | None = None,
624
+ extra_data: dict[str, Any] | None = None,
625
+ redirect_url: str | None = None,
626
+ ) -> dict[str, Any]:
629
627
  """
630
628
  Handle user registration with automatic token generation.
631
629
 
@@ -710,7 +708,7 @@ async def register_user(
710
708
  return {"success": False, "error": "Registration failed. Please try again."}
711
709
 
712
710
 
713
- async def _get_user_id_from_request(request: Request, user_id: Optional[str]) -> Optional[str]:
711
+ async def _get_user_id_from_request(request: Request, user_id: str | None) -> str | None:
714
712
  """Extract user_id from request if not provided."""
715
713
  if user_id:
716
714
  return user_id
@@ -773,9 +771,7 @@ async def _revoke_session(request: Request) -> None:
773
771
  await session_mgr.revoke_session_by_refresh_token(refresh_jti)
774
772
 
775
773
 
776
- async def logout_user(
777
- request: Request, response: Response, user_id: Optional[str] = None
778
- ) -> Response:
774
+ async def logout_user(request: Request, response: Response, user_id: str | None = None) -> Response:
779
775
  """
780
776
  Handle user logout with token revocation and cookie clearing.
781
777
 
@@ -17,7 +17,7 @@ This module is part of MDB_ENGINE - MongoDB Engine.
17
17
 
18
18
  import json
19
19
  from pathlib import Path
20
- from typing import Any, Dict, List, Optional
20
+ from typing import Any
21
21
 
22
22
  import click
23
23
 
@@ -210,7 +210,7 @@ class AppGenerator:
210
210
  output_dir: Path = Path("."),
211
211
  multi_site: bool = False,
212
212
  enable_ray: bool = False,
213
- read_scopes: Optional[List[str]] = None,
213
+ read_scopes: list[str] | None = None,
214
214
  ) -> Path:
215
215
  """
216
216
  Generate a new app with proper structure.
@@ -283,10 +283,10 @@ class AppGenerator:
283
283
  description: str,
284
284
  multi_site: bool,
285
285
  enable_ray: bool,
286
- read_scopes: List[str],
287
- ) -> Dict[str, Any]:
286
+ read_scopes: list[str],
287
+ ) -> dict[str, Any]:
288
288
  """Generate manifest.json content."""
289
- manifest: Dict[str, Any] = {
289
+ manifest: dict[str, Any] = {
290
290
  "schema_version": CURRENT_SCHEMA_VERSION,
291
291
  "slug": app_slug,
292
292
  "name": app_name,
@@ -476,7 +476,7 @@ def generate_manifest(
476
476
  )
477
477
 
478
478
  # Generate template manifest
479
- manifest: Dict[str, Any] = {
479
+ manifest: dict[str, Any] = {
480
480
  "schema_version": CURRENT_SCHEMA_VERSION,
481
481
  "slug": slug,
482
482
  "name": name,
mdb_engine/cli/utils.py CHANGED
@@ -8,12 +8,12 @@ This module is part of MDB_ENGINE - MongoDB Engine.
8
8
 
9
9
  import json
10
10
  from pathlib import Path
11
- from typing import Any, Dict
11
+ from typing import Any
12
12
 
13
13
  import click
14
14
 
15
15
 
16
- def load_manifest_file(file_path: Path) -> Dict[str, Any]:
16
+ def load_manifest_file(file_path: Path) -> dict[str, Any]:
17
17
  """
18
18
  Load a manifest JSON file.
19
19
 
@@ -36,7 +36,7 @@ def load_manifest_file(file_path: Path) -> Dict[str, Any]:
36
36
  raise click.ClickException(f"Invalid JSON in manifest file: {e}") from e
37
37
 
38
38
 
39
- def save_manifest_file(file_path: Path, manifest: Dict[str, Any]) -> None:
39
+ def save_manifest_file(file_path: Path, manifest: dict[str, Any]) -> None:
40
40
  """
41
41
  Save a manifest dictionary to a JSON file.
42
42
 
@@ -54,7 +54,7 @@ def save_manifest_file(file_path: Path, manifest: Dict[str, Any]) -> None:
54
54
  raise click.ClickException(f"Failed to write manifest file: {e}") from e
55
55
 
56
56
 
57
- def format_manifest_output(manifest: Dict[str, Any], format_type: str) -> str:
57
+ def format_manifest_output(manifest: dict[str, Any], format_type: str) -> str:
58
58
  """
59
59
  Format manifest for output.
60
60
 
mdb_engine/config.py CHANGED
@@ -7,7 +7,6 @@ with direct parameters as before.
7
7
  """
8
8
 
9
9
  import os
10
- from typing import Optional
11
10
 
12
11
  try:
13
12
  from pydantic import BaseSettings, Field
@@ -46,12 +45,12 @@ class EngineConfig:
46
45
 
47
46
  def __init__(
48
47
  self,
49
- mongo_uri: Optional[str] = None,
50
- db_name: Optional[str] = None,
51
- max_pool_size: Optional[int] = None,
52
- min_pool_size: Optional[int] = None,
53
- server_selection_timeout_ms: Optional[int] = None,
54
- authz_cache_ttl: Optional[int] = None,
48
+ mongo_uri: str | None = None,
49
+ db_name: str | None = None,
50
+ max_pool_size: int | None = None,
51
+ min_pool_size: int | None = None,
52
+ server_selection_timeout_ms: int | None = None,
53
+ authz_cache_ttl: int | None = None,
55
54
  ):
56
55
  """
57
56
  Initialize configuration.
@@ -10,8 +10,9 @@ This module is part of MDB_ENGINE - MongoDB Engine.
10
10
  import asyncio
11
11
  import logging
12
12
  import time
13
+ from collections.abc import Callable
13
14
  from pathlib import Path
14
- from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple
15
+ from typing import TYPE_CHECKING, Any, Optional
15
16
 
16
17
  from jsonschema import SchemaError
17
18
  from jsonschema import ValidationError as JsonSchemaValidationError
@@ -58,11 +59,11 @@ class AppRegistrationManager:
58
59
  self._mongo_db = mongo_db
59
60
  self.manifest_validator = manifest_validator
60
61
  self.manifest_parser = manifest_parser
61
- self._apps: Dict[str, Dict[str, Any]] = {}
62
+ self._apps: dict[str, dict[str, Any]] = {}
62
63
 
63
64
  async def validate_manifest(
64
65
  self, manifest: "ManifestDict"
65
- ) -> Tuple[bool, Optional[str], Optional[List[str]]]:
66
+ ) -> tuple[bool, str | None, list[str] | None]:
66
67
  """
67
68
  Validate a manifest against the schema.
68
69
 
@@ -115,13 +116,12 @@ class AppRegistrationManager:
115
116
  async def register_app(
116
117
  self,
117
118
  manifest: "ManifestDict",
118
- create_indexes_callback: Optional[Callable[[str, "ManifestDict"], Any]] = None,
119
- seed_data_callback: Optional[Callable[[str, Dict[str, List[Dict[str, Any]]]], Any]] = None,
120
- initialize_memory_callback: Optional[Callable[[str, Dict[str, Any]], Any]] = None,
121
- register_websockets_callback: Optional[Callable[[str, Dict[str, Any]], Any]] = None,
122
- setup_observability_callback: Optional[
123
- Callable[[str, "ManifestDict", Dict[str, Any]], Any]
124
- ] = None,
119
+ create_indexes_callback: Callable[[str, "ManifestDict"], Any] | None = None,
120
+ seed_data_callback: Callable[[str, dict[str, list[dict[str, Any]]]], Any] | None = None,
121
+ initialize_memory_callback: Callable[[str, dict[str, Any]], Any] | None = None,
122
+ register_websockets_callback: Callable[[str, dict[str, Any]], Any] | None = None,
123
+ setup_observability_callback: Callable[[str, "ManifestDict", dict[str, Any]], Any]
124
+ | None = None,
125
125
  ) -> bool:
126
126
  """
127
127
  Register an app from its manifest.
@@ -142,7 +142,7 @@ class AppRegistrationManager:
142
142
  """
143
143
  start_time = time.time()
144
144
 
145
- slug: Optional[str] = manifest.get("slug")
145
+ slug: str | None = manifest.get("slug")
146
146
  if not slug:
147
147
  contextual_logger.error(
148
148
  "Cannot register app: missing 'slug' in manifest",
@@ -359,7 +359,7 @@ class AppRegistrationManager:
359
359
  """
360
360
  return self._apps.get(slug)
361
361
 
362
- def list_apps(self) -> List[str]:
362
+ def list_apps(self) -> list[str]:
363
363
  """
364
364
  List all registered app slugs.
365
365
 
@@ -13,7 +13,6 @@ import base64
13
13
  import logging
14
14
  import secrets
15
15
  from datetime import datetime
16
- from typing import Optional
17
16
 
18
17
  from motor.motor_asyncio import AsyncIOMotorDatabase
19
18
  from pymongo.errors import OperationFailure, PyMongoError
@@ -188,7 +187,7 @@ class AppSecretsManager:
188
187
  logger.warning(f"Secret verification failed for app '{app_slug}'")
189
188
  return result
190
189
 
191
- async def get_app_secret(self, app_slug: str) -> Optional[str]:
190
+ async def get_app_secret(self, app_slug: str) -> str | None:
192
191
  """
193
192
  Get decrypted app secret (for rotation purposes only).
194
193
 
@@ -9,7 +9,6 @@ This module is part of MDB_ENGINE - MongoDB Engine.
9
9
 
10
10
  import logging
11
11
  import time
12
- from typing import Optional
13
12
 
14
13
  from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase
15
14
  from pymongo.errors import ConnectionFailure, ServerSelectionTimeoutError
@@ -57,8 +56,8 @@ class ConnectionManager:
57
56
  self.min_pool_size = min_pool_size
58
57
 
59
58
  # Connection state
60
- self._mongo_client: Optional[AsyncIOMotorClient] = None
61
- self._mongo_db: Optional[AsyncIOMotorDatabase] = None
59
+ self._mongo_client: AsyncIOMotorClient | None = None
60
+ self._mongo_db: AsyncIOMotorDatabase | None = None
62
61
  self._initialized: bool = False
63
62
 
64
63
  async def initialize(self) -> None:
@@ -242,7 +241,7 @@ class ConnectionManager:
242
241
  self._mongo_db = None
243
242
 
244
243
  @mongo_db.setter
245
- def mongo_db(self, value: Optional[AsyncIOMotorDatabase]) -> None:
244
+ def mongo_db(self, value: AsyncIOMotorDatabase | None) -> None:
246
245
  """Allow setting mongo_db property for testing purposes."""
247
246
  self._mongo_db = value
248
247
 
@@ -19,7 +19,6 @@ import base64
19
19
  import logging
20
20
  import os
21
21
  import secrets
22
- from typing import Tuple
23
22
 
24
23
  import cryptography.exceptions
25
24
  from cryptography.hazmat.primitives.ciphers.aead import AESGCM
@@ -121,7 +120,7 @@ class EnvelopeEncryptionService:
121
120
  """
122
121
  return secrets.token_bytes(AES_KEY_SIZE)
123
122
 
124
- def encrypt_secret(self, secret: str, master_key: bytes | None = None) -> Tuple[bytes, bytes]:
123
+ def encrypt_secret(self, secret: str, master_key: bytes | None = None) -> tuple[bytes, bytes]:
125
124
  """
126
125
  Encrypt a secret using envelope encryption.
127
126
 
mdb_engine/core/engine.py CHANGED
@@ -28,9 +28,10 @@ Usage:
28
28
  import logging
29
29
  import os
30
30
  import secrets
31
+ from collections.abc import Awaitable, Callable
31
32
  from contextlib import asynccontextmanager
32
33
  from pathlib import Path
33
- from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict, List, Optional, Tuple
34
+ from typing import TYPE_CHECKING, Any, Optional
34
35
 
35
36
  from motor.motor_asyncio import AsyncIOMotorClient
36
37
  from pymongo.errors import PyMongoError
@@ -94,7 +95,7 @@ class MongoDBEngine:
94
95
  self,
95
96
  mongo_uri: str,
96
97
  db_name: str,
97
- manifests_dir: Optional[Path] = None,
98
+ manifests_dir: Path | None = None,
98
99
  authz_provider: Optional["AuthorizationProvider"] = None,
99
100
  max_pool_size: int = DEFAULT_MAX_POOL_SIZE,
100
101
  min_pool_size: int = DEFAULT_MIN_POOL_SIZE,
@@ -142,17 +143,17 @@ class MongoDBEngine:
142
143
  self.manifest_parser = ManifestParser()
143
144
 
144
145
  # Initialize managers (will be set up after connection is established)
145
- self._app_registration_manager: Optional[AppRegistrationManager] = None
146
- self._index_manager: Optional[IndexManager] = None
147
- self._service_initializer: Optional[ServiceInitializer] = None
148
- self._encryption_service: Optional[EnvelopeEncryptionService] = None
149
- self._app_secrets_manager: Optional[AppSecretsManager] = None
146
+ self._app_registration_manager: AppRegistrationManager | None = None
147
+ self._index_manager: IndexManager | None = None
148
+ self._service_initializer: ServiceInitializer | None = None
149
+ self._encryption_service: EnvelopeEncryptionService | None = None
150
+ self._app_secrets_manager: AppSecretsManager | None = None
150
151
 
151
152
  # Store app read_scopes mapping for validation
152
- self._app_read_scopes: Dict[str, List[str]] = {}
153
+ self._app_read_scopes: dict[str, list[str]] = {}
153
154
 
154
155
  # Store app token cache for auto-retrieval
155
- self._app_token_cache: Dict[str, str] = {}
156
+ self._app_token_cache: dict[str, str] = {}
156
157
 
157
158
  async def initialize(self) -> None:
158
159
  """
@@ -300,9 +301,9 @@ class MongoDBEngine:
300
301
  def get_scoped_db(
301
302
  self,
302
303
  app_slug: str,
303
- app_token: Optional[str] = None,
304
- read_scopes: Optional[List[str]] = None,
305
- write_scope: Optional[str] = None,
304
+ app_token: str | None = None,
305
+ read_scopes: list[str] | None = None,
306
+ write_scope: str | None = None,
306
307
  auto_index: bool = True,
307
308
  ) -> ScopedMongoWrapper:
308
309
  """
@@ -435,9 +436,9 @@ class MongoDBEngine:
435
436
  async def get_scoped_db_async(
436
437
  self,
437
438
  app_slug: str,
438
- app_token: Optional[str] = None,
439
- read_scopes: Optional[List[str]] = None,
440
- write_scope: Optional[str] = None,
439
+ app_token: str | None = None,
440
+ read_scopes: list[str] | None = None,
441
+ write_scope: str | None = None,
441
442
  auto_index: bool = True,
442
443
  ) -> ScopedMongoWrapper:
443
444
  """
@@ -540,7 +541,7 @@ class MongoDBEngine:
540
541
 
541
542
  async def validate_manifest(
542
543
  self, manifest: "ManifestDict"
543
- ) -> Tuple[bool, Optional[str], Optional[List[str]]]:
544
+ ) -> tuple[bool, str | None, list[str] | None]:
544
545
  """
545
546
  Validate a manifest against the schema.
546
547
 
@@ -604,16 +605,16 @@ class MongoDBEngine:
604
605
  if self._index_manager and create_indexes:
605
606
  await self._index_manager.create_app_indexes(slug, manifest)
606
607
 
607
- async def seed_data_callback(slug: str, initial_data: Dict[str, Any]) -> None:
608
+ async def seed_data_callback(slug: str, initial_data: dict[str, Any]) -> None:
608
609
  if self._service_initializer:
609
610
  await self._service_initializer.seed_initial_data(slug, initial_data)
610
611
 
611
- async def initialize_memory_callback(slug: str, memory_config: Dict[str, Any]) -> None:
612
+ async def initialize_memory_callback(slug: str, memory_config: dict[str, Any]) -> None:
612
613
  if self._service_initializer:
613
614
  await self._service_initializer.initialize_memory_service(slug, memory_config)
614
615
 
615
616
  async def register_websockets_callback(
616
- slug: str, websockets_config: Dict[str, Any]
617
+ slug: str, websockets_config: dict[str, Any]
617
618
  ) -> None:
618
619
  if self._service_initializer:
619
620
  await self._service_initializer.register_websockets(slug, websockets_config)
@@ -621,7 +622,7 @@ class MongoDBEngine:
621
622
  async def setup_observability_callback(
622
623
  slug: str,
623
624
  manifest: "ManifestDict",
624
- observability_config: Dict[str, Any],
625
+ observability_config: dict[str, Any],
625
626
  ) -> None:
626
627
  if self._service_initializer:
627
628
  await self._service_initializer.setup_observability(
@@ -665,7 +666,7 @@ class MongoDBEngine:
665
666
 
666
667
  return result
667
668
 
668
- def get_websocket_config(self, slug: str) -> Optional[Dict[str, Any]]:
669
+ def get_websocket_config(self, slug: str) -> dict[str, Any] | None:
669
670
  """
670
671
  Get WebSocket configuration for an app.
671
672
 
@@ -851,7 +852,7 @@ class MongoDBEngine:
851
852
  raise RuntimeError("MongoDBEngine not initialized. Call initialize() first.")
852
853
  return await self._app_registration_manager.get_manifest(slug)
853
854
 
854
- def get_memory_service(self, slug: str) -> Optional[Any]:
855
+ def get_memory_service(self, slug: str) -> Any | None:
855
856
  """
856
857
  Get Mem0 memory service for an app.
857
858
 
@@ -875,7 +876,7 @@ class MongoDBEngine:
875
876
  return self._service_initializer.get_memory_service(slug)
876
877
  return None
877
878
 
878
- def get_embedding_service(self, slug: str) -> Optional[Any]:
879
+ def get_embedding_service(self, slug: str) -> Any | None:
879
880
  """
880
881
  Get EmbeddingService for an app.
881
882
 
@@ -900,7 +901,7 @@ class MongoDBEngine:
900
901
  return get_embedding_service_for_app(slug, self)
901
902
 
902
903
  @property
903
- def _apps(self) -> Dict[str, Any]:
904
+ def _apps(self) -> dict[str, Any]:
904
905
  """
905
906
  Get the apps dictionary (for backward compatibility with tests).
906
907
 
@@ -914,7 +915,7 @@ class MongoDBEngine:
914
915
  raise RuntimeError("MongoDBEngine not initialized. Call initialize() first.")
915
916
  return self._app_registration_manager._apps
916
917
 
917
- def list_apps(self) -> List[str]:
918
+ def list_apps(self) -> list[str]:
918
919
  """
919
920
  List all registered app slugs.
920
921
 
@@ -958,9 +959,9 @@ class MongoDBEngine:
958
959
 
959
960
  def __exit__(
960
961
  self,
961
- exc_type: Optional[type[BaseException]],
962
- exc_val: Optional[BaseException],
963
- exc_tb: Optional[Any],
962
+ exc_type: type[BaseException] | None,
963
+ exc_val: BaseException | None,
964
+ exc_tb: Any | None,
964
965
  ) -> None:
965
966
  """
966
967
  Context manager exit (synchronous).
@@ -991,9 +992,9 @@ class MongoDBEngine:
991
992
 
992
993
  async def __aexit__(
993
994
  self,
994
- exc_type: Optional[type[BaseException]],
995
- exc_val: Optional[BaseException],
996
- exc_tb: Optional[Any],
995
+ exc_type: type[BaseException] | None,
996
+ exc_val: BaseException | None,
997
+ exc_tb: Any | None,
997
998
  ) -> None:
998
999
  """
999
1000
  Async context manager exit.
@@ -1007,7 +1008,7 @@ class MongoDBEngine:
1007
1008
  """
1008
1009
  await self.shutdown()
1009
1010
 
1010
- async def get_health_status(self) -> Dict[str, Any]:
1011
+ async def get_health_status(self) -> dict[str, Any]:
1011
1012
  """
1012
1013
  Get health status of the MongoDB Engine.
1013
1014
 
@@ -1069,7 +1070,7 @@ class MongoDBEngine:
1069
1070
 
1070
1071
  return await health_checker.check_all()
1071
1072
 
1072
- def get_metrics(self) -> Dict[str, Any]:
1073
+ def get_metrics(self) -> dict[str, Any]:
1073
1074
  """
1074
1075
  Get metrics for the MongoDB Engine.
1075
1076
 
@@ -1089,13 +1090,11 @@ class MongoDBEngine:
1089
1090
  self,
1090
1091
  slug: str,
1091
1092
  manifest: Path,
1092
- title: Optional[str] = None,
1093
- on_startup: Optional[
1094
- Callable[["FastAPI", "MongoDBEngine", Dict[str, Any]], Awaitable[None]]
1095
- ] = None,
1096
- on_shutdown: Optional[
1097
- Callable[["FastAPI", "MongoDBEngine", Dict[str, Any]], Awaitable[None]]
1098
- ] = None,
1093
+ title: str | None = None,
1094
+ on_startup: Callable[["FastAPI", "MongoDBEngine", dict[str, Any]], Awaitable[None]]
1095
+ | None = None,
1096
+ on_shutdown: Callable[["FastAPI", "MongoDBEngine", dict[str, Any]], Awaitable[None]]
1097
+ | None = None,
1099
1098
  **fastapi_kwargs: Any,
1100
1099
  ) -> "FastAPI":
1101
1100
  """
@@ -1170,7 +1169,7 @@ class MongoDBEngine:
1170
1169
  app_title = title or pre_manifest.get("name", slug)
1171
1170
 
1172
1171
  # State that will be populated during initialization
1173
- app_manifest: Dict[str, Any] = {}
1172
+ app_manifest: dict[str, Any] = {}
1174
1173
  is_multi_site = False
1175
1174
 
1176
1175
  @asynccontextmanager
@@ -1506,7 +1505,7 @@ class MongoDBEngine:
1506
1505
  async def _initialize_shared_user_pool(
1507
1506
  self,
1508
1507
  app: "FastAPI",
1509
- manifest: Optional[Dict[str, Any]] = None,
1508
+ manifest: dict[str, Any] | None = None,
1510
1509
  ) -> None:
1511
1510
  """
1512
1511
  Initialize shared user pool, audit log, and set them on app.state.
@@ -1644,7 +1643,7 @@ class MongoDBEngine:
1644
1643
 
1645
1644
  return _lifespan
1646
1645
 
1647
- async def auto_retrieve_app_token(self, slug: str) -> Optional[str]:
1646
+ async def auto_retrieve_app_token(self, slug: str) -> str | None:
1648
1647
  """
1649
1648
  Auto-retrieve app token from environment or database.
1650
1649
 
@@ -1697,7 +1696,7 @@ class MongoDBEngine:
1697
1696
  )
1698
1697
  return None
1699
1698
 
1700
- def get_app_token(self, slug: str) -> Optional[str]:
1699
+ def get_app_token(self, slug: str) -> str | None:
1701
1700
  """
1702
1701
  Get cached app token for a slug.
1703
1702