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
@@ -24,7 +24,7 @@ class CustomerOut(BaseModel):
24
24
 
25
25
  class IntentCreateIn(BaseModel):
26
26
  amount: AmountMinor = Field(..., description="Minor units (e.g., cents)")
27
- currency: Currency = Field(..., example="USD")
27
+ currency: Currency = Field(..., json_schema_extra={"example": "USD"})
28
28
  description: Optional[str] = None
29
29
  capture_method: Literal["automatic", "manual"] = "automatic"
30
30
  payment_method_types: list[str] = Field(default_factory=list) # let provider default
@@ -169,3 +169,165 @@ class InvoiceOut(BaseModel):
169
169
  currency: Currency
170
170
  hosted_invoice_url: Optional[str] = None
171
171
  pdf_url: Optional[str] = None
172
+
173
+
174
+ class CaptureIn(BaseModel):
175
+ amount: Optional[AmountMinor] = None # partial capture supported
176
+
177
+
178
+ class IntentListFilter(BaseModel):
179
+ customer_provider_id: Optional[str] = None
180
+ status: Optional[str] = None
181
+ limit: Optional[int] = Field(default=50, ge=1, le=200)
182
+ cursor: Optional[str] = None # opaque provider cursor when supported
183
+
184
+
185
+ class UsageRecordIn(BaseModel):
186
+ # Stripe: subscription_item is the target for metered billing.
187
+ # If provider doesn't use subscription_item, allow provider_price_id as fallback.
188
+ subscription_item: Optional[str] = None
189
+ provider_price_id: Optional[str] = None
190
+ quantity: conint(ge=0)
191
+ timestamp: Optional[int] = None # Unix seconds; provider defaults to "now"
192
+ action: Optional[Literal["increment", "set"]] = "increment"
193
+
194
+
195
+ class InvoiceLineItemIn(BaseModel):
196
+ customer_provider_id: str
197
+ description: Optional[str] = None
198
+ unit_amount: AmountMinor
199
+ currency: Currency
200
+ quantity: Optional[int] = 1
201
+ provider_price_id: Optional[str] = None # if linked to a price, unit_amount may be ignored
202
+
203
+
204
+ class InvoicesListFilter(BaseModel):
205
+ customer_provider_id: Optional[str] = None
206
+ status: Optional[str] = None
207
+ limit: Optional[int] = Field(default=50, ge=1, le=200)
208
+ cursor: Optional[str] = None
209
+
210
+
211
+ class SetupIntentOut(BaseModel):
212
+ id: str
213
+ provider: str
214
+ provider_setup_intent_id: str
215
+ status: str
216
+ client_secret: Optional[str] = None
217
+ next_action: Optional[NextAction] = None
218
+
219
+
220
+ class DisputeOut(BaseModel):
221
+ id: str
222
+ provider: str
223
+ provider_dispute_id: str
224
+ amount: AmountMinor
225
+ currency: Currency
226
+ reason: Optional[str] = None
227
+ status: str
228
+ evidence_due_by: Optional[str] = None
229
+ created_at: Optional[str] = None
230
+
231
+
232
+ class PayoutOut(BaseModel):
233
+ id: str
234
+ provider: str
235
+ provider_payout_id: str
236
+ amount: AmountMinor
237
+ currency: Currency
238
+ status: str
239
+ arrival_date: Optional[str] = None
240
+ type: Optional[str] = None
241
+
242
+
243
+ class BalanceAmount(BaseModel):
244
+ currency: Currency
245
+ amount: AmountMinor
246
+
247
+
248
+ class BalanceSnapshotOut(BaseModel):
249
+ available: list[BalanceAmount] = Field(default_factory=list)
250
+ pending: list[BalanceAmount] = Field(default_factory=list)
251
+
252
+
253
+ class SetupIntentCreateIn(BaseModel):
254
+ payment_method_types: list[str] = Field(default_factory=lambda: ["card"])
255
+
256
+
257
+ class WebhookReplayIn(BaseModel):
258
+ event_ids: Optional[list[str]] = None
259
+
260
+
261
+ class WebhookReplayOut(BaseModel):
262
+ replayed: int
263
+
264
+
265
+ class WebhookAckOut(BaseModel):
266
+ ok: bool
267
+
268
+
269
+ class UsageRecordOut(BaseModel):
270
+ id: str
271
+ quantity: int
272
+ timestamp: Optional[int] = None
273
+ subscription_item: Optional[str] = None
274
+ provider_price_id: Optional[str] = None
275
+ action: Optional[Literal["increment", "set"]] = None
276
+
277
+
278
+ # -------- Customers list filter ----------
279
+ class CustomersListFilter(BaseModel):
280
+ provider: Optional[str] = None
281
+ user_id: Optional[str] = None
282
+ limit: Optional[int] = Field(default=50, ge=1, le=200)
283
+ cursor: Optional[str] = None # we’ll paginate on provider_customer_id asc
284
+
285
+
286
+ # -------- Products / Prices updates ----------
287
+ class ProductUpdateIn(BaseModel):
288
+ name: Optional[str] = None
289
+ active: Optional[bool] = None
290
+
291
+
292
+ class PriceUpdateIn(BaseModel):
293
+ active: Optional[bool] = None
294
+
295
+
296
+ # -------- Payment Method update ----------
297
+ class PaymentMethodUpdateIn(BaseModel):
298
+ # keep minimal + commonly supported card fields
299
+ name: Optional[str] = None
300
+ exp_month: Optional[int] = None
301
+ exp_year: Optional[int] = None
302
+ # extend here later with address fields (line1, city, etc.)
303
+
304
+
305
+ # -------- Refunds (list/get) ----------
306
+ class RefundOut(BaseModel):
307
+ id: str
308
+ provider: str
309
+ provider_refund_id: str
310
+ provider_payment_intent_id: Optional[str] = None
311
+ amount: AmountMinor
312
+ currency: Currency
313
+ status: str
314
+ reason: Optional[str] = None
315
+ created_at: Optional[str] = None
316
+
317
+
318
+ # -------- Invoice line items (list) ----------
319
+ class InvoiceLineItemOut(BaseModel):
320
+ id: str
321
+ description: Optional[str] = None
322
+ amount: AmountMinor
323
+ currency: Currency
324
+ quantity: Optional[int] = 1
325
+ provider_price_id: Optional[str] = None
326
+
327
+
328
+ # -------- Usage records list/get ----------
329
+ class UsageRecordListFilter(BaseModel):
330
+ subscription_item: Optional[str] = None
331
+ provider_price_id: Optional[str] = None
332
+ limit: Optional[int] = Field(default=50, ge=1, le=200)
333
+ cursor: Optional[str] = None