svc-infra 0.1.562__py3-none-any.whl → 0.1.654__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 (175) hide show
  1. svc_infra/apf_payments/README.md +732 -0
  2. svc_infra/apf_payments/models.py +142 -4
  3. svc_infra/apf_payments/provider/__init__.py +4 -0
  4. svc_infra/apf_payments/provider/aiydan.py +797 -0
  5. svc_infra/apf_payments/provider/base.py +178 -12
  6. svc_infra/apf_payments/provider/stripe.py +757 -48
  7. svc_infra/apf_payments/schemas.py +163 -1
  8. svc_infra/apf_payments/service.py +582 -42
  9. svc_infra/apf_payments/settings.py +22 -2
  10. svc_infra/api/fastapi/admin/__init__.py +3 -0
  11. svc_infra/api/fastapi/admin/add.py +231 -0
  12. svc_infra/api/fastapi/apf_payments/router.py +792 -73
  13. svc_infra/api/fastapi/apf_payments/setup.py +13 -4
  14. svc_infra/api/fastapi/auth/add.py +10 -4
  15. svc_infra/api/fastapi/auth/gaurd.py +67 -5
  16. svc_infra/api/fastapi/auth/routers/oauth_router.py +74 -34
  17. svc_infra/api/fastapi/auth/routers/session_router.py +63 -0
  18. svc_infra/api/fastapi/auth/settings.py +2 -0
  19. svc_infra/api/fastapi/billing/router.py +64 -0
  20. svc_infra/api/fastapi/billing/setup.py +19 -0
  21. svc_infra/api/fastapi/cache/add.py +9 -5
  22. svc_infra/api/fastapi/db/nosql/mongo/add.py +33 -27
  23. svc_infra/api/fastapi/db/sql/add.py +40 -18
  24. svc_infra/api/fastapi/db/sql/crud_router.py +176 -14
  25. svc_infra/api/fastapi/db/sql/session.py +16 -0
  26. svc_infra/api/fastapi/db/sql/users.py +13 -1
  27. svc_infra/api/fastapi/dependencies/ratelimit.py +116 -0
  28. svc_infra/api/fastapi/docs/add.py +160 -0
  29. svc_infra/api/fastapi/docs/landing.py +1 -1
  30. svc_infra/api/fastapi/docs/scoped.py +41 -6
  31. svc_infra/api/fastapi/middleware/errors/handlers.py +45 -7
  32. svc_infra/api/fastapi/middleware/graceful_shutdown.py +87 -0
  33. svc_infra/api/fastapi/middleware/idempotency.py +82 -42
  34. svc_infra/api/fastapi/middleware/idempotency_store.py +187 -0
  35. svc_infra/api/fastapi/middleware/optimistic_lock.py +37 -0
  36. svc_infra/api/fastapi/middleware/ratelimit.py +84 -11
  37. svc_infra/api/fastapi/middleware/ratelimit_store.py +84 -0
  38. svc_infra/api/fastapi/middleware/request_size_limit.py +36 -0
  39. svc_infra/api/fastapi/middleware/timeout.py +148 -0
  40. svc_infra/api/fastapi/openapi/mutators.py +244 -38
  41. svc_infra/api/fastapi/ops/add.py +73 -0
  42. svc_infra/api/fastapi/pagination.py +133 -32
  43. svc_infra/api/fastapi/routers/ping.py +1 -0
  44. svc_infra/api/fastapi/setup.py +23 -14
  45. svc_infra/api/fastapi/tenancy/add.py +19 -0
  46. svc_infra/api/fastapi/tenancy/context.py +112 -0
  47. svc_infra/api/fastapi/versioned.py +101 -0
  48. svc_infra/app/README.md +5 -5
  49. svc_infra/billing/__init__.py +23 -0
  50. svc_infra/billing/async_service.py +147 -0
  51. svc_infra/billing/jobs.py +230 -0
  52. svc_infra/billing/models.py +131 -0
  53. svc_infra/billing/quotas.py +101 -0
  54. svc_infra/billing/schemas.py +33 -0
  55. svc_infra/billing/service.py +115 -0
  56. svc_infra/bundled_docs/README.md +5 -0
  57. svc_infra/bundled_docs/__init__.py +1 -0
  58. svc_infra/bundled_docs/getting-started.md +6 -0
  59. svc_infra/cache/__init__.py +4 -0
  60. svc_infra/cache/add.py +158 -0
  61. svc_infra/cache/backend.py +5 -2
  62. svc_infra/cache/decorators.py +19 -1
  63. svc_infra/cache/keys.py +24 -4
  64. svc_infra/cli/__init__.py +32 -8
  65. svc_infra/cli/__main__.py +4 -0
  66. svc_infra/cli/cmds/__init__.py +10 -0
  67. svc_infra/cli/cmds/db/nosql/mongo/mongo_cmds.py +4 -3
  68. svc_infra/cli/cmds/db/nosql/mongo/mongo_scaffold_cmds.py +4 -4
  69. svc_infra/cli/cmds/db/sql/alembic_cmds.py +80 -11
  70. svc_infra/cli/cmds/db/sql/sql_export_cmds.py +80 -0
  71. svc_infra/cli/cmds/db/sql/sql_scaffold_cmds.py +3 -3
  72. svc_infra/cli/cmds/docs/docs_cmds.py +140 -0
  73. svc_infra/cli/cmds/dx/__init__.py +12 -0
  74. svc_infra/cli/cmds/dx/dx_cmds.py +99 -0
  75. svc_infra/cli/cmds/help.py +4 -0
  76. svc_infra/cli/cmds/jobs/__init__.py +1 -0
  77. svc_infra/cli/cmds/jobs/jobs_cmds.py +43 -0
  78. svc_infra/cli/cmds/obs/obs_cmds.py +4 -3
  79. svc_infra/cli/cmds/sdk/__init__.py +0 -0
  80. svc_infra/cli/cmds/sdk/sdk_cmds.py +102 -0
  81. svc_infra/data/add.py +61 -0
  82. svc_infra/data/backup.py +53 -0
  83. svc_infra/data/erasure.py +45 -0
  84. svc_infra/data/fixtures.py +40 -0
  85. svc_infra/data/retention.py +55 -0
  86. svc_infra/db/inbox.py +67 -0
  87. svc_infra/db/nosql/mongo/README.md +13 -13
  88. svc_infra/db/outbox.py +104 -0
  89. svc_infra/db/sql/repository.py +52 -12
  90. svc_infra/db/sql/resource.py +5 -0
  91. svc_infra/db/sql/templates/models_schemas/auth/schemas.py.tmpl +1 -1
  92. svc_infra/db/sql/templates/setup/env_async.py.tmpl +13 -8
  93. svc_infra/db/sql/templates/setup/env_sync.py.tmpl +9 -5
  94. svc_infra/db/sql/tenant.py +79 -0
  95. svc_infra/db/sql/utils.py +18 -4
  96. svc_infra/db/sql/versioning.py +14 -0
  97. svc_infra/docs/acceptance-matrix.md +71 -0
  98. svc_infra/docs/acceptance.md +44 -0
  99. svc_infra/docs/admin.md +425 -0
  100. svc_infra/docs/adr/0002-background-jobs-and-scheduling.md +40 -0
  101. svc_infra/docs/adr/0003-webhooks-framework.md +24 -0
  102. svc_infra/docs/adr/0004-tenancy-model.md +42 -0
  103. svc_infra/docs/adr/0005-data-lifecycle.md +86 -0
  104. svc_infra/docs/adr/0006-ops-slos-and-metrics.md +47 -0
  105. svc_infra/docs/adr/0007-docs-and-sdks.md +83 -0
  106. svc_infra/docs/adr/0008-billing-primitives.md +143 -0
  107. svc_infra/docs/adr/0009-acceptance-harness.md +40 -0
  108. svc_infra/docs/adr/0010-timeouts-and-resource-limits.md +54 -0
  109. svc_infra/docs/adr/0011-admin-scope-and-impersonation.md +73 -0
  110. svc_infra/docs/api.md +59 -0
  111. svc_infra/docs/auth.md +11 -0
  112. svc_infra/docs/billing.md +190 -0
  113. svc_infra/docs/cache.md +76 -0
  114. svc_infra/docs/cli.md +74 -0
  115. svc_infra/docs/contributing.md +34 -0
  116. svc_infra/docs/data-lifecycle.md +52 -0
  117. svc_infra/docs/database.md +14 -0
  118. svc_infra/docs/docs-and-sdks.md +62 -0
  119. svc_infra/docs/environment.md +114 -0
  120. svc_infra/docs/getting-started.md +63 -0
  121. svc_infra/docs/idempotency.md +111 -0
  122. svc_infra/docs/jobs.md +67 -0
  123. svc_infra/docs/observability.md +16 -0
  124. svc_infra/docs/ops.md +37 -0
  125. svc_infra/docs/rate-limiting.md +125 -0
  126. svc_infra/docs/repo-review.md +48 -0
  127. svc_infra/docs/security.md +176 -0
  128. svc_infra/docs/tenancy.md +35 -0
  129. svc_infra/docs/timeouts-and-resource-limits.md +147 -0
  130. svc_infra/docs/versioned-integrations.md +146 -0
  131. svc_infra/docs/webhooks.md +112 -0
  132. svc_infra/dx/add.py +63 -0
  133. svc_infra/dx/changelog.py +74 -0
  134. svc_infra/dx/checks.py +67 -0
  135. svc_infra/http/__init__.py +13 -0
  136. svc_infra/http/client.py +72 -0
  137. svc_infra/jobs/builtins/outbox_processor.py +38 -0
  138. svc_infra/jobs/builtins/webhook_delivery.py +90 -0
  139. svc_infra/jobs/easy.py +32 -0
  140. svc_infra/jobs/loader.py +45 -0
  141. svc_infra/jobs/queue.py +81 -0
  142. svc_infra/jobs/redis_queue.py +191 -0
  143. svc_infra/jobs/runner.py +75 -0
  144. svc_infra/jobs/scheduler.py +41 -0
  145. svc_infra/jobs/worker.py +40 -0
  146. svc_infra/mcp/svc_infra_mcp.py +85 -28
  147. svc_infra/obs/README.md +2 -0
  148. svc_infra/obs/add.py +54 -7
  149. svc_infra/obs/grafana/dashboards/http-overview.json +45 -0
  150. svc_infra/obs/metrics/__init__.py +53 -0
  151. svc_infra/obs/metrics.py +52 -0
  152. svc_infra/security/add.py +201 -0
  153. svc_infra/security/audit.py +130 -0
  154. svc_infra/security/audit_service.py +73 -0
  155. svc_infra/security/headers.py +52 -0
  156. svc_infra/security/hibp.py +95 -0
  157. svc_infra/security/jwt_rotation.py +53 -0
  158. svc_infra/security/lockout.py +96 -0
  159. svc_infra/security/models.py +255 -0
  160. svc_infra/security/org_invites.py +128 -0
  161. svc_infra/security/passwords.py +77 -0
  162. svc_infra/security/permissions.py +149 -0
  163. svc_infra/security/session.py +98 -0
  164. svc_infra/security/signed_cookies.py +80 -0
  165. svc_infra/webhooks/__init__.py +16 -0
  166. svc_infra/webhooks/add.py +322 -0
  167. svc_infra/webhooks/fastapi.py +37 -0
  168. svc_infra/webhooks/router.py +55 -0
  169. svc_infra/webhooks/service.py +67 -0
  170. svc_infra/webhooks/signing.py +30 -0
  171. svc_infra-0.1.654.dist-info/METADATA +154 -0
  172. {svc_infra-0.1.562.dist-info → svc_infra-0.1.654.dist-info}/RECORD +174 -56
  173. svc_infra-0.1.562.dist-info/METADATA +0 -79
  174. {svc_infra-0.1.562.dist-info → svc_infra-0.1.654.dist-info}/WHEEL +0 -0
  175. {svc_infra-0.1.562.dist-info → svc_infra-0.1.654.dist-info}/entry_points.txt +0 -0
@@ -3,58 +3,65 @@ from __future__ import annotations
3
3
  from typing import Any, Optional, Protocol
4
4
 
5
5
  from ..schemas import (
6
+ BalanceSnapshotOut,
6
7
  CustomerOut,
7
8
  CustomerUpsertIn,
9
+ DisputeOut,
8
10
  IntentCreateIn,
9
11
  IntentOut,
10
12
  InvoiceCreateIn,
13
+ InvoiceLineItemIn,
14
+ InvoiceLineItemOut,
11
15
  InvoiceOut,
12
16
  PaymentMethodAttachIn,
13
17
  PaymentMethodOut,
18
+ PaymentMethodUpdateIn,
19
+ PayoutOut,
14
20
  PriceCreateIn,
15
21
  PriceOut,
22
+ PriceUpdateIn,
16
23
  ProductCreateIn,
17
24
  ProductOut,
25
+ ProductUpdateIn,
18
26
  RefundIn,
27
+ RefundOut,
28
+ SetupIntentCreateIn,
29
+ SetupIntentOut,
19
30
  SubscriptionCreateIn,
20
31
  SubscriptionOut,
21
32
  SubscriptionUpdateIn,
33
+ UsageRecordIn,
34
+ UsageRecordListFilter,
35
+ UsageRecordOut,
22
36
  )
23
37
 
24
38
 
25
39
  class ProviderAdapter(Protocol):
26
40
  name: str
27
41
 
28
- # Customers
29
42
  async def ensure_customer(self, data: CustomerUpsertIn) -> CustomerOut:
30
43
  pass
31
44
 
32
- async def get_customer(self, provider_customer_id: str) -> Optional[CustomerOut]:
33
- pass
34
-
35
- # Payment Methods
36
45
  async def attach_payment_method(self, data: PaymentMethodAttachIn) -> PaymentMethodOut:
37
46
  pass
38
47
 
39
48
  async def list_payment_methods(self, provider_customer_id: str) -> list[PaymentMethodOut]:
40
49
  pass
41
50
 
42
- async def detach_payment_method(self, provider_method_id: str) -> None:
51
+ async def detach_payment_method(self, provider_method_id: str) -> PaymentMethodOut:
43
52
  pass
44
53
 
45
54
  async def set_default_payment_method(
46
55
  self, provider_customer_id: str, provider_method_id: str
47
- ) -> None:
56
+ ) -> PaymentMethodOut:
48
57
  pass
49
58
 
50
- # Products / Prices
51
59
  async def create_product(self, data: ProductCreateIn) -> ProductOut:
52
60
  pass
53
61
 
54
62
  async def create_price(self, data: PriceCreateIn) -> PriceOut:
55
63
  pass
56
64
 
57
- # Subscriptions
58
65
  async def create_subscription(self, data: SubscriptionCreateIn) -> SubscriptionOut:
59
66
  pass
60
67
 
@@ -68,7 +75,6 @@ class ProviderAdapter(Protocol):
68
75
  ) -> SubscriptionOut:
69
76
  pass
70
77
 
71
- # Invoices
72
78
  async def create_invoice(self, data: InvoiceCreateIn) -> InvoiceOut:
73
79
  pass
74
80
 
@@ -81,7 +87,6 @@ class ProviderAdapter(Protocol):
81
87
  async def pay_invoice(self, provider_invoice_id: str) -> InvoiceOut:
82
88
  pass
83
89
 
84
- # Intents
85
90
  async def create_intent(self, data: IntentCreateIn, *, user_id: str | None) -> IntentOut:
86
91
  pass
87
92
 
@@ -97,8 +102,169 @@ class ProviderAdapter(Protocol):
97
102
  async def hydrate_intent(self, provider_intent_id: str) -> IntentOut:
98
103
  pass
99
104
 
100
- # Webhooks
101
105
  async def verify_and_parse_webhook(
102
106
  self, signature: str | None, payload: bytes
103
107
  ) -> dict[str, Any]:
104
108
  pass
109
+
110
+ async def capture_intent(self, provider_intent_id: str, *, amount: int | None) -> IntentOut:
111
+ pass
112
+
113
+ async def list_intents(
114
+ self,
115
+ *,
116
+ customer_provider_id: str | None,
117
+ status: str | None,
118
+ limit: int,
119
+ cursor: str | None,
120
+ ) -> tuple[list[IntentOut], str | None]:
121
+ pass
122
+
123
+ async def add_invoice_line_item(
124
+ self, provider_invoice_id: str, data: InvoiceLineItemIn
125
+ ) -> InvoiceOut:
126
+ pass
127
+
128
+ async def list_invoices(
129
+ self,
130
+ *,
131
+ customer_provider_id: str | None,
132
+ status: str | None,
133
+ limit: int,
134
+ cursor: str | None,
135
+ ) -> tuple[list[InvoiceOut], str | None]:
136
+ pass
137
+
138
+ async def get_invoice(self, provider_invoice_id: str) -> InvoiceOut:
139
+ pass
140
+
141
+ async def preview_invoice(
142
+ self, *, customer_provider_id: str, subscription_id: str | None = None
143
+ ) -> InvoiceOut:
144
+ pass
145
+
146
+ async def create_usage_record(self, data: UsageRecordIn) -> UsageRecordOut:
147
+ pass
148
+
149
+ # --- Setup Intents ---
150
+ async def create_setup_intent(self, data: SetupIntentCreateIn) -> SetupIntentOut:
151
+ pass
152
+
153
+ async def confirm_setup_intent(self, provider_setup_intent_id: str) -> SetupIntentOut:
154
+ pass
155
+
156
+ async def get_setup_intent(self, provider_setup_intent_id: str) -> SetupIntentOut:
157
+ pass
158
+
159
+ # --- SCA / 3DS resume ---
160
+ async def resume_intent_after_action(self, provider_intent_id: str) -> IntentOut:
161
+ pass
162
+
163
+ # --- Disputes ---
164
+ async def list_disputes(
165
+ self, *, status: str | None, limit: int, cursor: str | None
166
+ ) -> tuple[list[DisputeOut], str | None]:
167
+ pass
168
+
169
+ async def get_dispute(self, provider_dispute_id: str) -> DisputeOut:
170
+ pass
171
+
172
+ async def submit_dispute_evidence(self, provider_dispute_id: str, evidence: dict) -> DisputeOut:
173
+ pass
174
+
175
+ # --- Balance & Payouts ---
176
+ async def get_balance_snapshot(self) -> BalanceSnapshotOut:
177
+ pass
178
+
179
+ async def list_payouts(
180
+ self, *, limit: int, cursor: str | None
181
+ ) -> tuple[list[PayoutOut], str | None]:
182
+ pass
183
+
184
+ async def get_payout(self, provider_payout_id: str) -> PayoutOut:
185
+ pass
186
+
187
+ # --- Customers ---
188
+ async def list_customers(
189
+ self, *, provider: str | None, user_id: str | None, limit: int, cursor: str | None
190
+ ) -> tuple[list[CustomerOut], str | None]:
191
+ """Optional: if not implemented, the service will list from local DB."""
192
+ pass
193
+
194
+ async def get_customer(self, provider_customer_id: str) -> Optional[CustomerOut]:
195
+ pass
196
+
197
+ # --- Products / Prices ---
198
+ async def get_product(self, provider_product_id: str) -> ProductOut:
199
+ pass
200
+
201
+ async def list_products(
202
+ self, *, active: bool | None, limit: int, cursor: str | None
203
+ ) -> tuple[list[ProductOut], str | None]:
204
+ pass
205
+
206
+ async def update_product(self, provider_product_id: str, data: ProductUpdateIn) -> ProductOut:
207
+ pass
208
+
209
+ async def get_price(self, provider_price_id: str) -> PriceOut:
210
+ pass
211
+
212
+ async def list_prices(
213
+ self,
214
+ *,
215
+ provider_product_id: str | None,
216
+ active: bool | None,
217
+ limit: int,
218
+ cursor: str | None,
219
+ ) -> tuple[list[PriceOut], str | None]:
220
+ pass
221
+
222
+ async def update_price(self, provider_price_id: str, data: PriceUpdateIn) -> PriceOut:
223
+ pass
224
+
225
+ # --- Subscriptions ---
226
+ async def get_subscription(self, provider_subscription_id: str) -> SubscriptionOut:
227
+ pass
228
+
229
+ async def list_subscriptions(
230
+ self,
231
+ *,
232
+ customer_provider_id: str | None,
233
+ status: str | None,
234
+ limit: int,
235
+ cursor: str | None,
236
+ ) -> tuple[list[SubscriptionOut], str | None]:
237
+ pass
238
+
239
+ # --- Payment Method (single + update) ---
240
+ async def get_payment_method(self, provider_method_id: str) -> PaymentMethodOut:
241
+ pass
242
+
243
+ async def update_payment_method(
244
+ self, provider_method_id: str, data: PaymentMethodUpdateIn
245
+ ) -> PaymentMethodOut:
246
+ pass
247
+
248
+ # --- Refunds list/get ---
249
+ async def list_refunds(
250
+ self, *, provider_payment_intent_id: str | None, limit: int, cursor: str | None
251
+ ) -> tuple[list[RefundOut], str | None]:
252
+ pass
253
+
254
+ async def get_refund(self, provider_refund_id: str) -> RefundOut:
255
+ pass
256
+
257
+ # --- Invoice line items list ---
258
+ async def list_invoice_line_items(
259
+ self, provider_invoice_id: str, *, limit: int, cursor: str | None
260
+ ) -> tuple[list[InvoiceLineItemOut], str | None]:
261
+ pass
262
+
263
+ # --- Usage records list/get ---
264
+ async def list_usage_records(
265
+ self, f: UsageRecordListFilter
266
+ ) -> tuple[list[UsageRecordOut], str | None]:
267
+ pass
268
+
269
+ async def get_usage_record(self, usage_record_id: str) -> UsageRecordOut:
270
+ pass