svc-infra 0.1.593__py3-none-any.whl → 0.1.595__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 svc-infra might be problematic. Click here for more details.

Files changed (33) hide show
  1. svc_infra/apf_payments/README.md +26 -0
  2. svc_infra/apf_payments/provider/aiydan.py +28 -2
  3. svc_infra/apf_payments/service.py +113 -20
  4. svc_infra/api/fastapi/apf_payments/router.py +67 -4
  5. svc_infra/api/fastapi/auth/add.py +10 -0
  6. svc_infra/api/fastapi/auth/gaurd.py +67 -5
  7. svc_infra/api/fastapi/auth/routers/oauth_router.py +79 -34
  8. svc_infra/api/fastapi/auth/routers/session_router.py +63 -0
  9. svc_infra/api/fastapi/auth/settings.py +2 -0
  10. svc_infra/api/fastapi/db/sql/users.py +13 -1
  11. svc_infra/api/fastapi/dependencies/ratelimit.py +66 -0
  12. svc_infra/api/fastapi/middleware/ratelimit.py +26 -11
  13. svc_infra/api/fastapi/middleware/ratelimit_store.py +78 -0
  14. svc_infra/api/fastapi/middleware/request_size_limit.py +36 -0
  15. svc_infra/api/fastapi/setup.py +2 -1
  16. svc_infra/obs/metrics/__init__.py +53 -0
  17. svc_infra/obs/metrics.py +52 -0
  18. svc_infra/security/audit.py +130 -0
  19. svc_infra/security/audit_service.py +73 -0
  20. svc_infra/security/headers.py +39 -0
  21. svc_infra/security/hibp.py +91 -0
  22. svc_infra/security/jwt_rotation.py +53 -0
  23. svc_infra/security/lockout.py +96 -0
  24. svc_infra/security/models.py +245 -0
  25. svc_infra/security/org_invites.py +128 -0
  26. svc_infra/security/passwords.py +77 -0
  27. svc_infra/security/permissions.py +148 -0
  28. svc_infra/security/session.py +98 -0
  29. svc_infra/security/signed_cookies.py +80 -0
  30. {svc_infra-0.1.593.dist-info → svc_infra-0.1.595.dist-info}/METADATA +1 -1
  31. {svc_infra-0.1.593.dist-info → svc_infra-0.1.595.dist-info}/RECORD +33 -16
  32. {svc_infra-0.1.593.dist-info → svc_infra-0.1.595.dist-info}/WHEEL +0 -0
  33. {svc_infra-0.1.593.dist-info → svc_infra-0.1.595.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,80 @@
1
+ from __future__ import annotations
2
+
3
+ import base64
4
+ import hmac
5
+ import json
6
+ import time
7
+ from hashlib import sha256
8
+ from typing import Any, Dict, List, Optional, Tuple
9
+
10
+
11
+ def _b64e(b: bytes) -> str:
12
+ return base64.urlsafe_b64encode(b).rstrip(b"=").decode()
13
+
14
+
15
+ def _b64d(s: str) -> bytes:
16
+ pad = "=" * (-len(s) % 4)
17
+ return base64.urlsafe_b64decode((s + pad).encode())
18
+
19
+
20
+ def _sign(data: bytes, key: bytes) -> str:
21
+ return _b64e(hmac.new(key, data, sha256).digest())
22
+
23
+
24
+ def _now() -> int:
25
+ return int(time.time())
26
+
27
+
28
+ def sign_cookie(
29
+ payload: Dict[str, Any],
30
+ *,
31
+ key: str,
32
+ expires_in: Optional[int] = None,
33
+ ) -> str:
34
+ """Produce a compact signed cookie value with optional expiry.
35
+
36
+ Format: base64url(json).base64url(hmac)
37
+ If expires_in is provided, 'exp' epoch seconds is injected into payload prior to signing.
38
+ """
39
+ body = dict(payload)
40
+ if expires_in is not None:
41
+ body.setdefault("exp", _now() + int(expires_in))
42
+ data = json.dumps(body, separators=(",", ":"), sort_keys=True).encode()
43
+ sig = _sign(data, key.encode())
44
+ return f"{_b64e(data)}.{sig}"
45
+
46
+
47
+ def verify_cookie(
48
+ value: str,
49
+ *,
50
+ key: str,
51
+ old_keys: Optional[List[str]] = None,
52
+ ) -> Tuple[bool, Optional[Dict[str, Any]]]:
53
+ """Verify a signed cookie against the primary key or any old key.
54
+
55
+ Returns (ok, payload). If ok is False, payload will be None.
56
+ Rejects if exp is present and in the past.
57
+ """
58
+ if not value or "." not in value:
59
+ return False, None
60
+ body_b64, sig = value.split(".", 1)
61
+ try:
62
+ data = _b64d(body_b64)
63
+ expected = _sign(data, key.encode())
64
+ if not hmac.compare_digest(sig, expected):
65
+ # try old keys
66
+ for k in old_keys or []:
67
+ if hmac.compare_digest(sig, _sign(data, k.encode())):
68
+ break
69
+ else:
70
+ return False, None
71
+ payload = json.loads(data.decode())
72
+ # Expire when current time reaches or exceeds exp
73
+ if "exp" in payload and _now() >= int(payload["exp"]):
74
+ return False, None
75
+ return True, payload
76
+ except Exception:
77
+ return False, None
78
+
79
+
80
+ __all__ = ["sign_cookie", "verify_cookie"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: svc-infra
3
- Version: 0.1.593
3
+ Version: 0.1.595
4
4
  Summary: Infrastructure for building and deploying prod-ready services
5
5
  License: MIT
6
6
  Keywords: fastapi,sqlalchemy,alembic,auth,infra,async,pydantic
@@ -1,25 +1,25 @@
1
1
  svc_infra/__init__.py,sha256=8maroJlM18MasrrLLcSbleK9pc0Q26Ek_sLvfafEG1c,49
2
- svc_infra/apf_payments/README.md,sha256=jW2YLnqsQbRkZQCbIwYL1fg0NnwT76KQ-Mxov75OX7A,22356
2
+ svc_infra/apf_payments/README.md,sha256=wqJrJcCkWIFMS0d1pUhYGt6NmgnxmYJcHFnUnm8Bf1Y,23321
3
3
  svc_infra/apf_payments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  svc_infra/apf_payments/alembic.py,sha256=XJIcCDOoaO1EeJbSx_qK9o4cBi430qyo5gECtjHIojw,299
5
5
  svc_infra/apf_payments/models.py,sha256=u4U5oszha5uulCIrNoajaFDIc5YmTlh2mtm-yJUvr9I,14251
6
6
  svc_infra/apf_payments/provider/__init__.py,sha256=zBh26eY7kcWHD4RXqAKfqaspY0_VE9thfts7aE8zbHg,142
7
- svc_infra/apf_payments/provider/aiydan.py,sha256=QyzNGsp5F9BB43QwI686-cNzxA2GASKDfJmCsMq86BY,30972
7
+ svc_infra/apf_payments/provider/aiydan.py,sha256=vraxdcPvaLyqF2O-lolKdhKNTWF7upuLpLvv3POt2Zs,31991
8
8
  svc_infra/apf_payments/provider/base.py,sha256=1t5znglpGFhjt4zdbuzE5VlHvGarFwzH2oscK8yyKNY,7678
9
9
  svc_infra/apf_payments/provider/registry.py,sha256=NZ4pUkFcbXNtqWEpFeI3NwoKRYGWe9fVQakmlrVLTKE,878
10
10
  svc_infra/apf_payments/provider/stripe.py,sha256=Xb_UjdobbBzK-an9cO1jRWiP6OHvki5MDp6JnS6a1-I,34392
11
11
  svc_infra/apf_payments/schemas.py,sha256=1fdGnrXrm8Rmk9nwDsbcvrVIyPL2o8HwbZ7-KY9-yZo,8561
12
- svc_infra/apf_payments/service.py,sha256=YjSjR7xB51_Xvq_gxibBCaXwTP2UwsF2gUAANN_OJOs,30799
12
+ svc_infra/apf_payments/service.py,sha256=Y5wtT9qnL57b_A3AAIL8fruliAitxeVyMPaYLZsv7ew,34851
13
13
  svc_infra/apf_payments/settings.py,sha256=vVWsvz_ajtVlRPH4N8ijSI4V7hUfjZFZT3h4wHRNa-s,2032
14
14
  svc_infra/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  svc_infra/api/fastapi/__init__.py,sha256=VVdQjak74_wTDqmvL05_C97vIFugQxPVU-3JQEFBgR8,747
16
16
  svc_infra/api/fastapi/apf_payments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- svc_infra/api/fastapi/apf_payments/router.py,sha256=zZM5gioXOHK4AfTGSmmqrsMNgqZ0AFBPxnN_at-DhNo,34071
17
+ svc_infra/api/fastapi/apf_payments/router.py,sha256=NVcLUNU-6Fx_3C_T_PbpsX1bN4LPVhiPuTSiqMcT7Ko,36275
18
18
  svc_infra/api/fastapi/apf_payments/setup.py,sha256=bk_LLLXyqTA-lqf0v-mdpqLEMbXB17U1IQjG-qSBejQ,2677
19
19
  svc_infra/api/fastapi/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  svc_infra/api/fastapi/auth/_cookies.py,sha256=U4heUmMnLezHx8U6ksuUEpSZ6sNMJcIO0gdLpmZ5FXw,1367
21
- svc_infra/api/fastapi/auth/add.py,sha256=HSVP3Y01_gXPnRiJG0tEA9OS-cBd-zmqsiDbLMFGWu4,9528
22
- svc_infra/api/fastapi/auth/gaurd.py,sha256=CMqambXyrLYnpIsfmy1yll8t_74U4KO-yyaIatmIgAI,6414
21
+ svc_infra/api/fastapi/auth/add.py,sha256=-GOLZv-O53wfegmMQsi1wgex_IKJWBJJ4vEQNONQpnU,10014
22
+ svc_infra/api/fastapi/auth/gaurd.py,sha256=j9k5V67MGr1s7m9yH4CPGAPkzAnnsqA5-xvrluYN3Ts,8751
23
23
  svc_infra/api/fastapi/auth/mfa/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  svc_infra/api/fastapi/auth/mfa/models.py,sha256=Te1cpGEBguUgul2NS50W_tHgybuu-TOIMPEBy53y9xc,1232
25
25
  svc_infra/api/fastapi/auth/mfa/pre_auth.py,sha256=ZsXIUNnObF8wx9-sz7PXGHrSSpaY2G0Ed5wwvu8TBzA,1379
@@ -32,10 +32,11 @@ svc_infra/api/fastapi/auth/providers.py,sha256=q-ftVn04dqYxx0rnc28uFKieQqMpc_Jnf
32
32
  svc_infra/api/fastapi/auth/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
33
  svc_infra/api/fastapi/auth/routers/account.py,sha256=IzLCk9e6ST8oorI8GWTuU0bfPyGvONqAjxadoE6L6Fg,1614
34
34
  svc_infra/api/fastapi/auth/routers/apikey_router.py,sha256=EoX-u1uZ0_r1dZ1hDO_PmG2sfSYZPa7uzj-4c520h8Y,5314
35
- svc_infra/api/fastapi/auth/routers/oauth_router.py,sha256=5NGjGzY5Bz5W-J7FC8LPXZ5LWVe0iBoVbNBmQ_vH3Cs,25069
35
+ svc_infra/api/fastapi/auth/routers/oauth_router.py,sha256=ZxGemG7jXa_CNlsCf-MWY2vQwBDgQ7DJamqpgerrmRQ,26575
36
+ svc_infra/api/fastapi/auth/routers/session_router.py,sha256=CVCum8Tczdj6ailRm1oRxys_EcNrOgBMYJT25yV4u3c,2359
36
37
  svc_infra/api/fastapi/auth/security.py,sha256=FU_XlaXHO1jocUbxeMOX3w2GWkR5ZXAcWbIUKTmOYvw,6482
37
38
  svc_infra/api/fastapi/auth/sender.py,sha256=7a47HXuP0JLR4NlFQVb3TpoQHOPYybKPJ06C2fMJaec,1811
38
- svc_infra/api/fastapi/auth/settings.py,sha256=KDqa74sHgu82kIXnzjo-2MOmaZHGWupove5ypljI8ak,3329
39
+ svc_infra/api/fastapi/auth/settings.py,sha256=H6jF9EOZOBbRJX0JugvirLMylJw64KK_32osGkJYRB8,3470
39
40
  svc_infra/api/fastapi/auth/state.py,sha256=_FAGOG36EPFAl2VbB6fdsFX0W9JNIdWN9X1_OVMz4Q8,1070
40
41
  svc_infra/api/fastapi/cache/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
42
  svc_infra/api/fastapi/cache/add.py,sha256=CX4TWsxrZ2EnN_TjVDOhQf382k8aUj2CXTG1GaZ5jU0,338
@@ -52,7 +53,8 @@ svc_infra/api/fastapi/db/sql/add.py,sha256=zrt6z4iVPEdq_f8dtBOJW_TRl-WlLBpW35KdT
52
53
  svc_infra/api/fastapi/db/sql/crud_router.py,sha256=GCNhGLZ2jfksBfgzqN20eStwpN9oUc9KPd0F0ztk4Bw,5030
53
54
  svc_infra/api/fastapi/db/sql/health.py,sha256=ELLgQerooHHnvZRhGueSAc4QJsb3C4RojUGIu_U-hA4,792
54
55
  svc_infra/api/fastapi/db/sql/session.py,sha256=DUBqKTRJAX4fqRz9B-w9eD9SpzZ8EUS862-GsjCL3ts,1869
55
- svc_infra/api/fastapi/db/sql/users.py,sha256=g7XI8GWm1h7i_xkDcGBOEy1aZw2XvXB-03Nxgh2Rm_g,4838
56
+ svc_infra/api/fastapi/db/sql/users.py,sha256=68HGJgYVTEjKJm4-DPPC8-6nwXJoCukmgrYIIOHEUjs,5346
57
+ svc_infra/api/fastapi/dependencies/ratelimit.py,sha256=us4iKKYZUqsoQ0xXuIJiLAsR8x-TlLMt6_ok8oiJSuY,1894
56
58
  svc_infra/api/fastapi/docs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
59
  svc_infra/api/fastapi/docs/landing.py,sha256=5JqJYCxQDCWy-BeDLfkv7OBlzWQKSGWUCYXQ51hojG8,4627
58
60
  svc_infra/api/fastapi/docs/scoped.py,sha256=AuN35Op-9fUvHQCLOBtRjd5eWSpB5C9EAW_7-Boxmfo,7540
@@ -75,8 +77,10 @@ svc_infra/api/fastapi/middleware/errors/catchall.py,sha256=TG0W71UCDbfgLNdIaIv6m
75
77
  svc_infra/api/fastapi/middleware/errors/exceptions.py,sha256=857_bdMgQugf8rb7U6ZaTZV3aiFTfBzFaUg80YUfAYE,475
76
78
  svc_infra/api/fastapi/middleware/errors/handlers.py,sha256=9Em_Z6PXTm9gM9ulEYwY02DqRuNxz6LLh8z5CMheruY,7128
77
79
  svc_infra/api/fastapi/middleware/idempotency.py,sha256=Wc9uzFQmatPAGF6oEP35YxRsIn_dBsRL1vyMk6y6A4k,3284
78
- svc_infra/api/fastapi/middleware/ratelimit.py,sha256=xcrgOq7IEtMXg9Tzd2u45xhdkPSEc1Zd55OFzLoacmw,1718
80
+ svc_infra/api/fastapi/middleware/ratelimit.py,sha256=a1KZ_TCSkSn5WlPOIEZ0lw5sUsrAMMBXdiDNFVWFi5k,2044
81
+ svc_infra/api/fastapi/middleware/ratelimit_store.py,sha256=LmJR8-kkW42rzOjls9lG1SBtCKjVY7L2Y_bNKHNY3-A,2553
79
82
  svc_infra/api/fastapi/middleware/request_id.py,sha256=Iru7ypTdK_n76lwziEGDWoVF4FKS0Ps1PMASYmzK8ek,768
83
+ svc_infra/api/fastapi/middleware/request_size_limit.py,sha256=AcGqaB-F7Tbhg-at7ViT4Bpifst34jFneDBlUBjgo5I,1248
80
84
  svc_infra/api/fastapi/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
85
  svc_infra/api/fastapi/openapi/apply.py,sha256=VAwRfcYSLCSKIpO1dp9okG1MXvkZuciU41jrSSuvUpI,1697
82
86
  svc_infra/api/fastapi/openapi/conventions.py,sha256=e6gUsFyfEGvz3KkUimjAWMfF7_fonMJ3IoGvQZjpvfs,7171
@@ -93,7 +97,7 @@ svc_infra/api/fastapi/paths/prefix.py,sha256=I1xEt1lKDlOPn2Oa-y_1B-Q8JCwAPpu3_F_
93
97
  svc_infra/api/fastapi/paths/user.py,sha256=z8xv_A3dPhG366ezJU1c839oHbU3tEg06rbx3HUUuL0,323
94
98
  svc_infra/api/fastapi/routers/__init__.py,sha256=pbyrfVZzrMFgX11K47TvTS94yN0q-t-BdrVrGG9QyDk,9163
95
99
  svc_infra/api/fastapi/routers/ping.py,sha256=4M1xJ5nPu_CSvHHSD2DQJKzS7Mf5m8J-Ok9bXSEwudA,540
96
- svc_infra/api/fastapi/setup.py,sha256=_gXq1oiRavlpTuDHpN640oJhku0HwlGn3s5-So4vg9I,9507
100
+ svc_infra/api/fastapi/setup.py,sha256=zm7mgyhTZVFNbrRaCerBN8fDfglpWStAYLMZHfVmEjU,9574
97
101
  svc_infra/app/README.md,sha256=jWbgyvP90NobTgxlkwyzCZpFOS-zDSkKw0JoRNauCrs,5074
98
102
  svc_infra/app/__init__.py,sha256=za20ALo_kvJMgf7R_kF98DWk3h9acmvhYrCMhThcSmU,209
99
103
  svc_infra/app/env.py,sha256=AOs4ksLZDXoAWrXeSnkYZ2yyS4UP68QUYfaWDcQ1QfA,4426
@@ -188,11 +192,12 @@ svc_infra/obs/README.md,sha256=wOABJUOhuj0ftGt24ZfuChlFNJTYvYq4KM_rcRIdWRU,7884
188
192
  svc_infra/obs/__init__.py,sha256=t5DgkiuuhHnfAHChzYqCI1-Fpr68iQ0A1nHOLFIlAuM,75
189
193
  svc_infra/obs/add.py,sha256=j8Nsv6k7mGM7tGFIoCxgSpFNV93G_WmtSbCIBohHRT4,2026
190
194
  svc_infra/obs/cloud_dash.py,sha256=1rg6NO9kjhN3zCugfBqDxkTN5nQqjQRC5ye2gFxb6g4,4329
191
- svc_infra/obs/metrics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
195
+ svc_infra/obs/metrics/__init__.py,sha256=fSqtl2CNV24j13tihK-bsflt0wSSGK8qjxFKvKWBSfk,1421
192
196
  svc_infra/obs/metrics/asgi.py,sha256=d9qvOdwJmkIHeB_YV_QcqflXYXYWiriffuqBaaLRbCg,8873
193
197
  svc_infra/obs/metrics/base.py,sha256=IHpNJk12whfBEerW9Qkj2fV5Iiw_H-Od4gqPcdOVWNs,2649
194
198
  svc_infra/obs/metrics/http.py,sha256=n-AuzOETxxLPpo0h-kTGHyn9-F19od_Eh1pM3C0oVCs,3003
195
199
  svc_infra/obs/metrics/sqlalchemy.py,sha256=pLvp2hdV_4Wa4Bsottd1Kh8Hlru3PXUtUugJMtCdFNM,2353
200
+ svc_infra/obs/metrics.py,sha256=hvvgY3oO1ssqB-IDAeRXf-l4AjrfU-mqKYEsLG0-WF4,1475
196
201
  svc_infra/obs/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
197
202
  svc_infra/obs/providers/compose_cloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
198
203
  svc_infra/obs/providers/compose_cloud/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -229,8 +234,20 @@ svc_infra/obs/templates/sidecars/railway/README.md,sha256=3tFBJPKvmxjg3FjtfGYLwB
229
234
  svc_infra/obs/templates/sidecars/railway/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
230
235
  svc_infra/obs/templates/sidecars/railway/agent.yaml,sha256=hYv35yG92XEP_4joMFmMcVTD-4fG_zHitmChjreUJh4,516
231
236
  svc_infra/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
237
+ svc_infra/security/audit.py,sha256=r_OrXAz5uIa2o5nVD-8lsWqzggRGDKfp2sWd8URlz-E,4355
238
+ svc_infra/security/audit_service.py,sha256=Xd5V7Iz6PS4YpxmLyJypnaqr8poaaleKwAI2uFF7y1A,2351
239
+ svc_infra/security/headers.py,sha256=1VkAe-IWzPYfHxeZAnv9QwtzD7fP9NBTJw3mflW17bQ,1461
240
+ svc_infra/security/hibp.py,sha256=VrPoz2vjHEC3AjC4f-IyRWMx43qN3Xpb5pYoSQqQSAE,2728
241
+ svc_infra/security/jwt_rotation.py,sha256=VXPRQeSCoJEl2kQnIJZELWIS0-rGUZrxCdH4Fr47vig,1767
242
+ svc_infra/security/lockout.py,sha256=KdKN9FWejuzHRKS9jXzi_f3-lNF6QZyiEDBXCej0LSY,2804
243
+ svc_infra/security/models.py,sha256=US5jxgeZf7C_tWW3QZRj5RTuRZE_yS6RHZBEK0ea9tA,9535
244
+ svc_infra/security/org_invites.py,sha256=TuXEstZp5GfRQflz8OR2q6m7GpSOonSxm0QU7ojkbH0,3876
245
+ svc_infra/security/passwords.py,sha256=zUiduHFOWYT7USzMkBntI3-LNEyVMn2A78CvaKpB7MY,2459
246
+ svc_infra/security/permissions.py,sha256=fQm7-OcJJkWsScDcjS2gwmqaW93zQqltaHRl6bviIik,4527
247
+ svc_infra/security/session.py,sha256=JkClqoZ-Moo9yqHzCREXMVSpzyjbn2Zh6zCjtWO93Ik,2848
248
+ svc_infra/security/signed_cookies.py,sha256=2t61BgjsBaTzU46bt7IUJo7lwDRE9_eS4vmAQXJ8mlY,2219
232
249
  svc_infra/utils.py,sha256=VX1yjTx61-YvAymyRhGy18DhybiVdPddiYD_FlKTbJU,952
233
- svc_infra-0.1.593.dist-info/METADATA,sha256=ppEktfFTTLD_Sn6UR81aJgkVCewdHOUj4ZjpnLp1GS8,3527
234
- svc_infra-0.1.593.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
235
- svc_infra-0.1.593.dist-info/entry_points.txt,sha256=6x_nZOsjvn6hRZsMgZLgTasaCSKCgAjsGhACe_CiP0U,48
236
- svc_infra-0.1.593.dist-info/RECORD,,
250
+ svc_infra-0.1.595.dist-info/METADATA,sha256=wxxuM6mbWaeSQdvV72wZI6B_XrCfpj1kMwGdecksB3I,3527
251
+ svc_infra-0.1.595.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
252
+ svc_infra-0.1.595.dist-info/entry_points.txt,sha256=6x_nZOsjvn6hRZsMgZLgTasaCSKCgAjsGhACe_CiP0U,48
253
+ svc_infra-0.1.595.dist-info/RECORD,,