geek-cafe-saas-sdk 0.7.4__py3-none-any.whl → 0.8.0__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.

Potentially problematic release.


This version of geek-cafe-saas-sdk might be problematic. Click here for more details.

Files changed (131) hide show
  1. geek_cafe_saas_sdk/__init__.py +1 -1
  2. geek_cafe_saas_sdk/core/anonymous_context.py +321 -0
  3. geek_cafe_saas_sdk/core/request_context.py +184 -0
  4. geek_cafe_saas_sdk/decorators/__init__.py +1 -1
  5. geek_cafe_saas_sdk/decorators/auth.py +6 -6
  6. geek_cafe_saas_sdk/decorators/core.py +44 -44
  7. geek_cafe_saas_sdk/domains/analytics/services/website_analytics_service.py +1 -3
  8. geek_cafe_saas_sdk/domains/analytics/services/website_analytics_summary_service.py +1 -3
  9. geek_cafe_saas_sdk/domains/analytics/services/website_analytics_tally_service.py +15 -3
  10. geek_cafe_saas_sdk/domains/auth/handlers/users/create/app.py +1 -1
  11. geek_cafe_saas_sdk/domains/auth/handlers/users/delete/app.py +1 -1
  12. geek_cafe_saas_sdk/domains/auth/handlers/users/get/app.py +1 -1
  13. geek_cafe_saas_sdk/domains/auth/handlers/users/list/app.py +1 -1
  14. geek_cafe_saas_sdk/domains/auth/handlers/users/update/app.py +1 -1
  15. geek_cafe_saas_sdk/domains/auth/services/resource_permission_service.py +1 -4
  16. geek_cafe_saas_sdk/domains/auth/services/user_service.py +0 -2
  17. geek_cafe_saas_sdk/domains/communities/handlers/communities/create/app.py +1 -1
  18. geek_cafe_saas_sdk/domains/communities/handlers/communities/delete/app.py +1 -1
  19. geek_cafe_saas_sdk/domains/communities/handlers/communities/get/app.py +1 -1
  20. geek_cafe_saas_sdk/domains/communities/handlers/communities/list/app.py +1 -1
  21. geek_cafe_saas_sdk/domains/communities/handlers/communities/update/app.py +1 -1
  22. geek_cafe_saas_sdk/domains/communities/services/community_member_service.py +1 -3
  23. geek_cafe_saas_sdk/domains/communities/services/community_service.py +3 -3
  24. geek_cafe_saas_sdk/domains/events/handlers/attendees/app.py +1 -1
  25. geek_cafe_saas_sdk/domains/events/handlers/cancel/app.py +1 -1
  26. geek_cafe_saas_sdk/domains/events/handlers/check_in/app.py +1 -1
  27. geek_cafe_saas_sdk/domains/events/handlers/create/app.py +1 -1
  28. geek_cafe_saas_sdk/domains/events/handlers/delete/app.py +1 -1
  29. geek_cafe_saas_sdk/domains/events/handlers/get/app.py +1 -1
  30. geek_cafe_saas_sdk/domains/events/handlers/invite/app.py +1 -1
  31. geek_cafe_saas_sdk/domains/events/handlers/list/app.py +1 -1
  32. geek_cafe_saas_sdk/domains/events/handlers/publish/app.py +1 -1
  33. geek_cafe_saas_sdk/domains/events/handlers/rsvp/app.py +1 -1
  34. geek_cafe_saas_sdk/domains/events/handlers/update/app.py +1 -1
  35. geek_cafe_saas_sdk/domains/events/services/event_attendee_service.py +1 -2
  36. geek_cafe_saas_sdk/domains/events/services/event_service.py +6 -4
  37. geek_cafe_saas_sdk/domains/files/handlers/README.md +1 -1
  38. geek_cafe_saas_sdk/domains/files/handlers/files/create/app.py +1 -1
  39. geek_cafe_saas_sdk/domains/files/handlers/files/download/app.py +1 -1
  40. geek_cafe_saas_sdk/domains/files/handlers/files/get/app.py +1 -1
  41. geek_cafe_saas_sdk/domains/files/handlers/files/list/app.py +1 -1
  42. geek_cafe_saas_sdk/domains/files/handlers/lineage/create_derived/app.py +1 -1
  43. geek_cafe_saas_sdk/domains/files/handlers/lineage/create_main/app.py +1 -1
  44. geek_cafe_saas_sdk/domains/files/handlers/lineage/download_bundle/app.py +1 -1
  45. geek_cafe_saas_sdk/domains/files/handlers/lineage/get_lineage/app.py +1 -1
  46. geek_cafe_saas_sdk/domains/files/handlers/lineage/prepare_bundle/app.py +1 -1
  47. geek_cafe_saas_sdk/domains/files/models/file.py +16 -6
  48. geek_cafe_saas_sdk/domains/files/services/directory_service.py +34 -9
  49. geek_cafe_saas_sdk/domains/files/services/file_system_service.py +38 -3
  50. geek_cafe_saas_sdk/domains/files/services/file_version_service.py +33 -36
  51. geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/create/app.py +1 -1
  52. geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/delete/app.py +1 -1
  53. geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/get/app.py +1 -1
  54. geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/list/app.py +1 -1
  55. geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/update/app.py +1 -1
  56. geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/create/app.py +1 -1
  57. geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/delete/app.py +1 -1
  58. geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/get/app.py +1 -1
  59. geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/list/app.py +1 -1
  60. geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/update/app.py +1 -1
  61. geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/create/app.py +1 -1
  62. geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/delete/app.py +1 -1
  63. geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/get/app.py +1 -1
  64. geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/list/app.py +3 -2
  65. geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/update/app.py +1 -1
  66. geek_cafe_saas_sdk/domains/messaging/services/chat_channel_service.py +35 -2
  67. geek_cafe_saas_sdk/domains/messaging/services/chat_message_service.py +20 -3
  68. geek_cafe_saas_sdk/domains/messaging/services/contact_thread_service.py +1 -3
  69. geek_cafe_saas_sdk/domains/notifications/handlers/create_webhook/app.py +1 -1
  70. geek_cafe_saas_sdk/domains/notifications/handlers/get/app.py +1 -1
  71. geek_cafe_saas_sdk/domains/notifications/handlers/get_preferences/app.py +1 -1
  72. geek_cafe_saas_sdk/domains/notifications/handlers/list/app.py +1 -1
  73. geek_cafe_saas_sdk/domains/notifications/handlers/list_webhooks/app.py +1 -1
  74. geek_cafe_saas_sdk/domains/notifications/handlers/mark_read/app.py +1 -1
  75. geek_cafe_saas_sdk/domains/notifications/handlers/send/app.py +1 -1
  76. geek_cafe_saas_sdk/domains/notifications/handlers/update_preferences/app.py +1 -1
  77. geek_cafe_saas_sdk/domains/notifications/services/notification_service.py +1 -2
  78. geek_cafe_saas_sdk/domains/payments/handlers/billing_accounts/create/app.py +1 -1
  79. geek_cafe_saas_sdk/domains/payments/handlers/billing_accounts/get/app.py +1 -1
  80. geek_cafe_saas_sdk/domains/payments/handlers/billing_accounts/update/app.py +1 -1
  81. geek_cafe_saas_sdk/domains/payments/handlers/payment_intents/create/app.py +1 -1
  82. geek_cafe_saas_sdk/domains/payments/handlers/payment_intents/get/app.py +1 -1
  83. geek_cafe_saas_sdk/domains/payments/handlers/payments/get/app.py +1 -1
  84. geek_cafe_saas_sdk/domains/payments/handlers/payments/list/app.py +1 -1
  85. geek_cafe_saas_sdk/domains/payments/handlers/payments/record/app.py +1 -1
  86. geek_cafe_saas_sdk/domains/payments/handlers/refunds/create/app.py +1 -1
  87. geek_cafe_saas_sdk/domains/payments/handlers/refunds/get/app.py +1 -1
  88. geek_cafe_saas_sdk/domains/payments/services/payment_service.py +1 -2
  89. geek_cafe_saas_sdk/domains/subscriptions/handlers/README.md +2 -2
  90. geek_cafe_saas_sdk/domains/subscriptions/handlers/addons/create/app.py +1 -1
  91. geek_cafe_saas_sdk/domains/subscriptions/handlers/addons/get/app.py +1 -1
  92. geek_cafe_saas_sdk/domains/subscriptions/handlers/addons/list/app.py +1 -1
  93. geek_cafe_saas_sdk/domains/subscriptions/handlers/addons/update/app.py +1 -1
  94. geek_cafe_saas_sdk/domains/subscriptions/handlers/discounts/create/app.py +1 -1
  95. geek_cafe_saas_sdk/domains/subscriptions/handlers/discounts/get/app.py +1 -1
  96. geek_cafe_saas_sdk/domains/subscriptions/handlers/discounts/validate/app.py +1 -1
  97. geek_cafe_saas_sdk/domains/subscriptions/handlers/plans/create/app.py +1 -1
  98. geek_cafe_saas_sdk/domains/subscriptions/handlers/plans/get/app.py +1 -1
  99. geek_cafe_saas_sdk/domains/subscriptions/handlers/plans/list/app.py +1 -1
  100. geek_cafe_saas_sdk/domains/subscriptions/handlers/plans/update/app.py +1 -1
  101. geek_cafe_saas_sdk/domains/subscriptions/handlers/usage/aggregate/app.py +1 -1
  102. geek_cafe_saas_sdk/domains/subscriptions/handlers/usage/record/app.py +1 -1
  103. geek_cafe_saas_sdk/domains/subscriptions/services/subscription_manager_service.py +0 -2
  104. geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/activate/app.py +1 -1
  105. geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/active/app.py +1 -1
  106. geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/cancel/app.py +1 -1
  107. geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/get/app.py +1 -1
  108. geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/list/app.py +1 -1
  109. geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/record_payment/app.py +1 -1
  110. geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/get/app.py +1 -1
  111. geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/me/app.py +1 -1
  112. geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/signup/app.py +1 -1
  113. geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/update/app.py +1 -1
  114. geek_cafe_saas_sdk/domains/tenancy/services/subscription_service.py +3 -3
  115. geek_cafe_saas_sdk/domains/tenancy/services/tenant_service.py +3 -3
  116. geek_cafe_saas_sdk/domains/voting/handlers/votes/delete/app.py +1 -1
  117. geek_cafe_saas_sdk/domains/voting/handlers/votes/get/app.py +1 -1
  118. geek_cafe_saas_sdk/domains/voting/handlers/votes/list/app.py +1 -1
  119. geek_cafe_saas_sdk/domains/voting/handlers/votes/update/app.py +1 -1
  120. geek_cafe_saas_sdk/domains/voting/services/vote_service.py +1 -5
  121. geek_cafe_saas_sdk/domains/voting/services/vote_summary_service.py +1 -5
  122. geek_cafe_saas_sdk/domains/voting/services/vote_tally_service.py +10 -3
  123. geek_cafe_saas_sdk/lambda_handlers/_base/base_handler.py +40 -6
  124. geek_cafe_saas_sdk/lambda_handlers/_base/service_pool.py +157 -12
  125. geek_cafe_saas_sdk/middleware/authorization.py +1 -1
  126. geek_cafe_saas_sdk/middleware/cors.py +8 -8
  127. geek_cafe_saas_sdk/services/database_service.py +76 -5
  128. {geek_cafe_saas_sdk-0.7.4.dist-info → geek_cafe_saas_sdk-0.8.0.dist-info}/METADATA +16 -16
  129. {geek_cafe_saas_sdk-0.7.4.dist-info → geek_cafe_saas_sdk-0.8.0.dist-info}/RECORD +131 -129
  130. {geek_cafe_saas_sdk-0.7.4.dist-info → geek_cafe_saas_sdk-0.8.0.dist-info}/WHEEL +0 -0
  131. {geek_cafe_saas_sdk-0.7.4.dist-info → geek_cafe_saas_sdk-0.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -9,6 +9,7 @@ from typing import Dict, Any, Optional, List
9
9
  from boto3_assist.dynamodb.dynamodb import DynamoDB
10
10
  from boto3_assist.dynamodb.dynamodb_index import DynamoDBKey
11
11
  from geek_cafe_saas_sdk.services.database_service import DatabaseService
12
+ from geek_cafe_saas_sdk.core.request_context import RequestContext
12
13
  from geek_cafe_saas_sdk.core.service_result import ServiceResult
13
14
  from geek_cafe_saas_sdk.core.service_errors import ValidationError, NotFoundError, AccessDeniedError
14
15
  from geek_cafe_saas_sdk.domains.messaging.models import ChatChannel, ChatChannelMember
@@ -18,8 +19,7 @@ import datetime as dt
18
19
  class ChatChannelService(DatabaseService[ChatChannel]):
19
20
  """Service for ChatChannel database operations."""
20
21
 
21
- def __init__(self, *, dynamodb: DynamoDB = None, table_name: str = None):
22
- super().__init__(dynamodb=dynamodb, table_name=table_name)
22
+
23
23
 
24
24
  def create(self, tenant_id: str, user_id: str, payload: Dict[str, Any]) -> ServiceResult[ChatChannel]:
25
25
  """
@@ -36,6 +36,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
36
36
  ServiceResult with ChatChannel
37
37
  """
38
38
  try:
39
+ # Set targets for security validation
40
+ if self._request_context:
41
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
39
42
  # Validate required fields
40
43
  required_fields = ['name']
41
44
  self._validate_required_fields(payload, required_fields)
@@ -91,6 +94,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
91
94
  ServiceResult with ChatChannel
92
95
  """
93
96
  try:
97
+ # Set targets for security validation
98
+ if self._request_context:
99
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
94
100
  channel = self._get_model_by_id(resource_id, ChatChannel)
95
101
 
96
102
  if not channel:
@@ -131,6 +137,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
131
137
  ServiceResult with list of ChatChannels
132
138
  """
133
139
  try:
140
+ # Set targets for security validation
141
+ if self._request_context:
142
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
134
143
  temp_channel = ChatChannel()
135
144
  temp_channel.tenant_id = tenant_id
136
145
  temp_channel.channel_type = channel_type
@@ -171,6 +180,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
171
180
  ServiceResult with list of ChatChannels
172
181
  """
173
182
  try:
183
+ # Set targets for security validation
184
+ if self._request_context:
185
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
174
186
  temp_channel = ChatChannel()
175
187
  temp_channel.tenant_id = tenant_id
176
188
 
@@ -246,6 +258,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
246
258
  ServiceResult with list of ChatChannels
247
259
  """
248
260
  try:
261
+ # Set targets for security validation
262
+ if self._request_context:
263
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
249
264
  # Get user's channel memberships (fast via GSI1)
250
265
  memberships_result = self.list_user_channels_fast(user_id, limit)
251
266
  if not memberships_result.success:
@@ -285,6 +300,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
285
300
  ServiceResult with updated ChatChannel
286
301
  """
287
302
  try:
303
+ # Set targets for security validation
304
+ if self._request_context:
305
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
288
306
  channel_result = self.get_by_id(channel_id, tenant_id, user_id)
289
307
  if not channel_result.success:
290
308
  return channel_result
@@ -331,6 +349,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
331
349
  ServiceResult with updated ChatChannel
332
350
  """
333
351
  try:
352
+ # Set targets for security validation
353
+ if self._request_context:
354
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
334
355
  channel_result = self.get_by_id(channel_id, tenant_id, user_id)
335
356
  if not channel_result.success:
336
357
  return channel_result
@@ -409,6 +430,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
409
430
  ServiceResult with updated ChatChannel
410
431
  """
411
432
  try:
433
+ # Set targets for security validation
434
+ if self._request_context:
435
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
412
436
  channel_result = self.get_by_id(channel_id, tenant_id, user_id)
413
437
  if not channel_result.success:
414
438
  return channel_result
@@ -441,6 +465,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
441
465
  ServiceResult with updated ChatChannel
442
466
  """
443
467
  try:
468
+ # Set targets for security validation
469
+ if self._request_context:
470
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
444
471
  # For unarchive, we need to get the channel even if archived
445
472
  channel = self._get_model_by_id(channel_id, ChatChannel)
446
473
  if not channel:
@@ -476,6 +503,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
476
503
  ServiceResult with updated ChatChannel
477
504
  """
478
505
  try:
506
+ # Set targets for security validation
507
+ if self._request_context:
508
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
479
509
  channel = self._get_model_by_id(resource_id, ChatChannel)
480
510
 
481
511
  if not channel:
@@ -521,6 +551,9 @@ class ChatChannelService(DatabaseService[ChatChannel]):
521
551
  ServiceResult with boolean success
522
552
  """
523
553
  try:
554
+ # Set targets for security validation
555
+ if self._request_context:
556
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
524
557
  channel = self._get_model_by_id(resource_id, ChatChannel)
525
558
 
526
559
  if not channel:
@@ -8,6 +8,7 @@ ChatMessageService for managing individual chat messages.
8
8
  from typing import Dict, Any, Optional, List
9
9
  from boto3_assist.dynamodb.dynamodb import DynamoDB
10
10
  from geek_cafe_saas_sdk.services.database_service import DatabaseService
11
+ from geek_cafe_saas_sdk.core.request_context import RequestContext
11
12
  from .chat_channel_service import ChatChannelService
12
13
  from geek_cafe_saas_sdk.core.service_result import ServiceResult
13
14
  from geek_cafe_saas_sdk.core.service_errors import ValidationError, NotFoundError, AccessDeniedError
@@ -20,11 +21,12 @@ class ChatMessageService(DatabaseService[ChatMessage]):
20
21
  """Service for ChatMessage database operations."""
21
22
 
22
23
  def __init__(self, *, dynamodb: DynamoDB = None, table_name: str = None,
24
+ request_context: Optional[RequestContext] = None,
23
25
  channel_service: ChatChannelService = None):
24
- super().__init__(dynamodb=dynamodb, table_name=table_name)
25
- # Channel service for updating channel metadata
26
+ super().__init__(dynamodb=dynamodb, table_name=table_name, request_context=request_context)
27
+ # Channel service for updating channel metadata (share request_context)
26
28
  self.channel_service = channel_service or ChatChannelService(
27
- dynamodb=dynamodb, table_name=table_name
29
+ dynamodb=dynamodb, table_name=table_name, request_context=request_context
28
30
  )
29
31
  # Query helper for sharded message reads
30
32
  self.query_helper = MessageQueryHelper(dynamodb, table_name)
@@ -42,6 +44,9 @@ class ChatMessageService(DatabaseService[ChatMessage]):
42
44
  ServiceResult with ChatMessage
43
45
  """
44
46
  try:
47
+ # Set targets for security validation
48
+ if self._request_context:
49
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
45
50
  # Validate required fields
46
51
  required_fields = ['channel_id', 'content']
47
52
  self._validate_required_fields(payload, required_fields)
@@ -129,6 +134,9 @@ class ChatMessageService(DatabaseService[ChatMessage]):
129
134
  ServiceResult with ChatMessage
130
135
  """
131
136
  try:
137
+ # Set targets for security validation
138
+ if self._request_context:
139
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
132
140
  message = self._get_model_by_id(resource_id, ChatMessage)
133
141
 
134
142
  if not message:
@@ -174,6 +182,9 @@ class ChatMessageService(DatabaseService[ChatMessage]):
174
182
  ServiceResult with list of ChatMessages and pagination metadata
175
183
  """
176
184
  try:
185
+ # Set targets for security validation
186
+ if self._request_context:
187
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
177
188
  # Verify user has access to the channel
178
189
  channel_result = self.channel_service.get_by_id(channel_id, tenant_id, user_id)
179
190
  if not channel_result.success:
@@ -382,6 +393,9 @@ class ChatMessageService(DatabaseService[ChatMessage]):
382
393
  ServiceResult with updated ChatMessage
383
394
  """
384
395
  try:
396
+ # Set targets for security validation
397
+ if self._request_context:
398
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
385
399
  message = self._get_model_by_id(resource_id, ChatMessage)
386
400
 
387
401
  if not message:
@@ -423,6 +437,9 @@ class ChatMessageService(DatabaseService[ChatMessage]):
423
437
  ServiceResult with boolean success
424
438
  """
425
439
  try:
440
+ # Set targets for security validation
441
+ if self._request_context:
442
+ self._request_context.set_targets(tenant_id=tenant_id, user_id=user_id)
426
443
  message = self._get_model_by_id(resource_id, ChatMessage)
427
444
 
428
445
  if not message:
@@ -16,9 +16,7 @@ import datetime as dt
16
16
 
17
17
  class ContactThreadService(DatabaseService[ContactThread]):
18
18
  """Service for ContactThread database operations."""
19
-
20
- def __init__(self, *, dynamodb: DynamoDB = None, table_name: str = None):
21
- super().__init__(dynamodb=dynamodb, table_name=table_name)
19
+
22
20
 
23
21
  def _user_has_cross_tenant_access(self, user_context: Optional[Dict[str, str]]) -> bool:
24
22
  """
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
12
12
  )
13
13
 
14
14
 
15
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
15
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
16
16
  """
17
17
  Create webhook subscription.
18
18
 
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
12
12
  )
13
13
 
14
14
 
15
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
15
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
16
16
  """
17
17
  Get a notification by ID.
18
18
 
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
12
12
  )
13
13
 
14
14
 
15
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
15
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
16
16
  """
17
17
  Get user notification preferences.
18
18
 
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
12
12
  )
13
13
 
14
14
 
15
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
15
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
16
16
  """
17
17
  List notifications for current user.
18
18
 
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
12
12
  )
13
13
 
14
14
 
15
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
15
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
16
16
  """
17
17
  List webhook subscriptions.
18
18
 
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
12
12
  )
13
13
 
14
14
 
15
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
15
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
16
16
  """
17
17
  Mark notification as read.
18
18
 
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
12
12
  )
13
13
 
14
14
 
15
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
15
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
16
16
  """
17
17
  Send a notification.
18
18
 
@@ -12,7 +12,7 @@ handler_wrapper = create_handler(
12
12
  )
13
13
 
14
14
 
15
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
15
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
16
16
  """
17
17
  Update user notification preferences.
18
18
 
@@ -35,8 +35,7 @@ class NotificationService(DatabaseService[Notification]):
35
35
  - Webhook subscriptions
36
36
  """
37
37
 
38
- def __init__(self, *, dynamodb: Optional[DynamoDB] = None, table_name: Optional[str] = None):
39
- super().__init__(dynamodb=dynamodb, table_name=table_name)
38
+
40
39
 
41
40
  # ========================================================================
42
41
  # Abstract Method Implementations (Required by DatabaseService)
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
17
17
  )
18
18
 
19
19
 
20
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
21
  """
22
22
  Create a new billing account.
23
23
 
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
17
17
  )
18
18
 
19
19
 
20
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
21
  """
22
22
  Get billing account by ID.
23
23
 
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
17
17
  )
18
18
 
19
19
 
20
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
21
  """
22
22
  Update a billing account.
23
23
 
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
17
17
  )
18
18
 
19
19
 
20
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
21
  """
22
22
  Create a payment intent.
23
23
 
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
17
17
  )
18
18
 
19
19
 
20
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
21
  """
22
22
  Get payment intent by ID.
23
23
 
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
17
17
  )
18
18
 
19
19
 
20
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
21
  """
22
22
  Get payment by ID.
23
23
 
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
17
17
  )
18
18
 
19
19
 
20
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
21
  """
22
22
  List payments for a tenant or billing account.
23
23
 
@@ -18,7 +18,7 @@ handler_wrapper = create_handler(
18
18
  )
19
19
 
20
20
 
21
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
22
22
  """
23
23
  Record a settled payment.
24
24
 
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
17
17
  )
18
18
 
19
19
 
20
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
21
  """
22
22
  Create a refund for a payment.
23
23
 
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
17
17
  )
18
18
 
19
19
 
20
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
21
  """
22
22
  Get refund by ID.
23
23
 
@@ -21,8 +21,7 @@ from geek_cafe_saas_sdk.domains.payments.models.refund import Refund
21
21
  class PaymentService(DatabaseService[Payment]):
22
22
  """Service for managing payments, billing accounts, and refunds."""
23
23
 
24
- def __init__(self, *, dynamodb: Optional[DynamoDB] = None, table_name: Optional[str] = None):
25
- super().__init__(dynamodb=dynamodb, table_name=table_name)
24
+
26
25
 
27
26
  # Abstract method implementations (delegating to specific methods)
28
27
  def create(self, **kwargs) -> ServiceResult[Payment]:
@@ -341,7 +341,7 @@ PlanListFunction:
341
341
  Handlers support dependency injection for testing:
342
342
 
343
343
  ```python
344
- from handlers.plans.list.app import handler
344
+ from handlers.plans.list.app import lambda_handler
345
345
 
346
346
  # Mock service
347
347
  class MockService:
@@ -350,7 +350,7 @@ class MockService:
350
350
 
351
351
  # Test
352
352
  event = {"queryStringParameters": {"status": "active"}}
353
- response = handler(event, None, injected_service=MockService())
353
+ response = lambda_handler(event, None, injected_service=MockService())
354
354
  ```
355
355
 
356
356
  ---
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
16
16
  )
17
17
 
18
18
 
19
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
19
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
20
  """
21
21
  Create a new addon.
22
22
 
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
17
17
  )
18
18
 
19
19
 
20
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
21
  """
22
22
  Get an addon by ID.
23
23
 
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
17
17
  )
18
18
 
19
19
 
20
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
21
  """
22
22
  List public addons.
23
23
 
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
16
16
  )
17
17
 
18
18
 
19
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
19
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
20
  """
21
21
  Update an addon.
22
22
 
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
16
16
  )
17
17
 
18
18
 
19
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
19
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
20
  """
21
21
  Create a new discount/promo code.
22
22
 
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
16
16
  )
17
17
 
18
18
 
19
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
19
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
20
  """
21
21
  Get a discount by ID.
22
22
 
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
17
17
  )
18
18
 
19
19
 
20
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
21
  """
22
22
  Validate a discount code.
23
23
 
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
16
16
  )
17
17
 
18
18
 
19
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
19
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
20
  """
21
21
  Create a new subscription plan.
22
22
 
@@ -17,7 +17,7 @@ handler_wrapper = create_handler(
17
17
  )
18
18
 
19
19
 
20
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
21
  """
22
22
  Get a subscription plan by ID.
23
23
 
@@ -18,7 +18,7 @@ handler_wrapper = create_handler(
18
18
  )
19
19
 
20
20
 
21
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
21
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
22
22
  """
23
23
  List public subscription plans.
24
24
 
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
16
16
  )
17
17
 
18
18
 
19
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
19
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
20
  """
21
21
  Update a subscription plan.
22
22
 
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
16
16
  )
17
17
 
18
18
 
19
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
19
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
20
  """
21
21
  Get aggregated usage for a billing period.
22
22
 
@@ -16,7 +16,7 @@ handler_wrapper = create_handler(
16
16
  )
17
17
 
18
18
 
19
- def handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
19
+ def lambda_handler(event: Dict[str, Any], context: Any, injected_service=None) -> Dict[str, Any]:
20
20
  """
21
21
  Record a usage event for metered billing.
22
22
 
@@ -30,8 +30,6 @@ class SubscriptionManagerService(DatabaseService[Plan]):
30
30
  per-tenant subscription instances.
31
31
  """
32
32
 
33
- def __init__(self, *, dynamodb: Optional[DynamoDB] = None, table_name: Optional[str] = None):
34
- super().__init__(dynamodb=dynamodb, table_name=table_name)
35
33
 
36
34
  # ========================================================================
37
35
  # Abstract Method Implementations (DatabaseService)
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
10
10
 
11
11
  subscription_service_pool = ServicePool(SubscriptionService)
12
12
 
13
- def handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
13
+ def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
14
14
  """
15
15
  Lambda handler for activating a subscription (upgrade/downgrade).
16
16
 
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
9
9
 
10
10
  subscription_service_pool = ServicePool(SubscriptionService)
11
11
 
12
- def handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
12
+ def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
13
13
  """
14
14
  Lambda handler for retrieving the tenant's active subscription.
15
15
 
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
10
10
 
11
11
  subscription_service_pool = ServicePool(SubscriptionService)
12
12
 
13
- def handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
13
+ def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
14
14
  """
15
15
  Lambda handler for canceling a subscription.
16
16
 
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
9
9
 
10
10
  subscription_service_pool = ServicePool(SubscriptionService)
11
11
 
12
- def handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
12
+ def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
13
13
  """
14
14
  Lambda handler for retrieving a subscription by ID.
15
15
 
@@ -9,7 +9,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
9
9
 
10
10
  subscription_service_pool = ServicePool(SubscriptionService)
11
11
 
12
- def handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
12
+ def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
13
13
  """
14
14
  Lambda handler for listing subscription history for a tenant.
15
15
 
@@ -10,7 +10,7 @@ from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
10
10
 
11
11
  subscription_service_pool = ServicePool(SubscriptionService)
12
12
 
13
- def handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
13
+ def lambda_handler(event: Dict[str, Any], context: object, injected_service=None) -> Dict[str, Any]:
14
14
  """
15
15
  Lambda handler for recording a payment on a subscription.
16
16