fin-infra 0.1.81__py3-none-any.whl → 0.1.83__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 (96) hide show
  1. fin_infra/analytics/__init__.py +3 -2
  2. fin_infra/analytics/add.py +21 -21
  3. fin_infra/analytics/ease.py +19 -20
  4. fin_infra/analytics/portfolio.py +6 -6
  5. fin_infra/analytics/projections.py +1 -3
  6. fin_infra/banking/__init__.py +27 -27
  7. fin_infra/banking/history.py +4 -5
  8. fin_infra/banking/utils.py +19 -18
  9. fin_infra/brokerage/__init__.py +22 -24
  10. fin_infra/budgets/__init__.py +3 -3
  11. fin_infra/budgets/add.py +16 -17
  12. fin_infra/cashflows/__init__.py +2 -2
  13. fin_infra/categorization/add.py +2 -3
  14. fin_infra/categorization/engine.py +6 -6
  15. fin_infra/categorization/llm_layer.py +6 -5
  16. fin_infra/categorization/rules.py +2 -4
  17. fin_infra/categorization/taxonomy.py +2 -2
  18. fin_infra/chat/__init__.py +5 -5
  19. fin_infra/chat/planning.py +0 -1
  20. fin_infra/cli/cmds/scaffold_cmds.py +10 -11
  21. fin_infra/clients/plaid.py +1 -1
  22. fin_infra/compliance/__init__.py +5 -5
  23. fin_infra/credit/add.py +6 -7
  24. fin_infra/credit/experian/auth.py +2 -2
  25. fin_infra/credit/experian/client.py +1 -1
  26. fin_infra/credit/experian/provider.py +4 -4
  27. fin_infra/crypto/__init__.py +7 -9
  28. fin_infra/documents/add.py +6 -8
  29. fin_infra/documents/analysis.py +8 -8
  30. fin_infra/documents/ease.py +14 -14
  31. fin_infra/documents/ocr.py +7 -7
  32. fin_infra/documents/storage.py +21 -13
  33. fin_infra/exceptions.py +0 -1
  34. fin_infra/goals/__init__.py +8 -8
  35. fin_infra/goals/add.py +30 -30
  36. fin_infra/goals/funding.py +1 -1
  37. fin_infra/goals/management.py +2 -3
  38. fin_infra/goals/milestones.py +1 -2
  39. fin_infra/goals/models.py +7 -11
  40. fin_infra/insights/__init__.py +2 -2
  41. fin_infra/insights/aggregator.py +1 -1
  42. fin_infra/investments/__init__.py +1 -1
  43. fin_infra/investments/add.py +23 -23
  44. fin_infra/investments/providers/base.py +2 -3
  45. fin_infra/investments/providers/plaid.py +9 -9
  46. fin_infra/investments/providers/snaptrade.py +10 -10
  47. fin_infra/markets/__init__.py +1 -1
  48. fin_infra/models/__init__.py +10 -10
  49. fin_infra/models/brokerage.py +2 -1
  50. fin_infra/models/candle.py +1 -0
  51. fin_infra/models/money.py +1 -0
  52. fin_infra/models/quotes.py +4 -3
  53. fin_infra/models/tax.py +2 -1
  54. fin_infra/models/transactions.py +3 -4
  55. fin_infra/net_worth/insights.py +0 -1
  56. fin_infra/normalization/__init__.py +2 -2
  57. fin_infra/normalization/providers/exchangerate.py +5 -5
  58. fin_infra/providers/banking/plaid_client.py +5 -5
  59. fin_infra/providers/banking/teller_client.py +7 -6
  60. fin_infra/providers/base.py +1 -1
  61. fin_infra/providers/brokerage/alpaca.py +3 -3
  62. fin_infra/providers/market/alphavantage.py +5 -10
  63. fin_infra/providers/market/ccxt_crypto.py +2 -2
  64. fin_infra/providers/market/coingecko.py +5 -6
  65. fin_infra/providers/market/yahoo.py +5 -5
  66. fin_infra/providers/tax/__init__.py +1 -1
  67. fin_infra/providers/tax/irs.py +1 -1
  68. fin_infra/providers/tax/mock.py +5 -5
  69. fin_infra/providers/tax/taxbit.py +1 -1
  70. fin_infra/recurring/__init__.py +6 -6
  71. fin_infra/recurring/add.py +5 -4
  72. fin_infra/recurring/detector.py +7 -7
  73. fin_infra/recurring/detectors_llm.py +6 -6
  74. fin_infra/recurring/ease.py +2 -4
  75. fin_infra/recurring/insights.py +13 -13
  76. fin_infra/recurring/normalizer.py +1 -1
  77. fin_infra/recurring/normalizers.py +4 -4
  78. fin_infra/recurring/summary.py +4 -6
  79. fin_infra/scaffold/budgets.py +6 -6
  80. fin_infra/scaffold/goals.py +1 -1
  81. fin_infra/security/__init__.py +8 -8
  82. fin_infra/security/encryption.py +6 -6
  83. fin_infra/security/models.py +7 -7
  84. fin_infra/security/pii_filter.py +6 -6
  85. fin_infra/settings.py +2 -1
  86. fin_infra/tax/__init__.py +1 -1
  87. fin_infra/tax/add.py +3 -2
  88. fin_infra/tax/tlh.py +5 -5
  89. fin_infra/utils/http.py +4 -3
  90. fin_infra/utils/retry.py +1 -1
  91. {fin_infra-0.1.81.dist-info → fin_infra-0.1.83.dist-info}/METADATA +1 -1
  92. fin_infra-0.1.83.dist-info/RECORD +180 -0
  93. fin_infra-0.1.81.dist-info/RECORD +0 -180
  94. {fin_infra-0.1.81.dist-info → fin_infra-0.1.83.dist-info}/LICENSE +0 -0
  95. {fin_infra-0.1.81.dist-info → fin_infra-0.1.83.dist-info}/WHEEL +0 -0
  96. {fin_infra-0.1.81.dist-info → fin_infra-0.1.83.dist-info}/entry_points.txt +0 -0
@@ -8,25 +8,25 @@ Provides:
8
8
  """
9
9
 
10
10
  from .add import add_financial_security, generate_encryption_key
11
- from .audit import log_pii_access, get_audit_logs, clear_audit_logs
11
+ from .audit import clear_audit_logs, get_audit_logs, log_pii_access
12
12
  from .encryption import ProviderTokenEncryption
13
- from .models import ProviderTokenMetadata, PIIAccessLog
13
+ from .models import PIIAccessLog, ProviderTokenMetadata
14
14
  from .pii_filter import FinancialPIIFilter
15
15
  from .pii_patterns import (
16
- SSN_PATTERN,
17
16
  ACCOUNT_PATTERN,
18
- ROUTING_PATTERN,
19
17
  CARD_PATTERN,
20
18
  CVV_PATTERN,
21
19
  EIN_PATTERN,
22
- luhn_checksum,
20
+ ROUTING_PATTERN,
21
+ SSN_PATTERN,
23
22
  is_valid_routing_number,
23
+ luhn_checksum,
24
24
  )
25
25
  from .token_store import (
26
- store_provider_token,
27
- get_provider_token,
28
- delete_provider_token,
29
26
  ProviderToken,
27
+ delete_provider_token,
28
+ get_provider_token,
29
+ store_provider_token,
30
30
  )
31
31
 
32
32
  __all__ = [
@@ -7,7 +7,7 @@ Encrypt/decrypt financial provider API tokens at rest.
7
7
  import base64
8
8
  import json
9
9
  import os
10
- from typing import Any, Optional, cast
10
+ from typing import Any, cast
11
11
 
12
12
  from cryptography.fernet import Fernet, InvalidToken
13
13
 
@@ -37,7 +37,7 @@ class ProviderTokenEncryption:
37
37
  >>> token = encryption.decrypt(encrypted, context={"user_id": "user123", "provider": "plaid"})
38
38
  """
39
39
 
40
- def __init__(self, key: Optional[bytes] = None):
40
+ def __init__(self, key: bytes | None = None):
41
41
  """
42
42
  Initialize token encryption.
43
43
 
@@ -64,7 +64,7 @@ class ProviderTokenEncryption:
64
64
  raise ValueError(f"Invalid encryption key: {e}") from e
65
65
 
66
66
  def encrypt(
67
- self, token: str, context: Optional[dict[str, Any]] = None, key_id: Optional[str] = None
67
+ self, token: str, context: dict[str, Any] | None = None, key_id: str | None = None
68
68
  ) -> str:
69
69
  """
70
70
  Encrypt provider token with optional context.
@@ -104,7 +104,7 @@ class ProviderTokenEncryption:
104
104
  def decrypt(
105
105
  self,
106
106
  encrypted_token: str,
107
- context: Optional[dict[str, Any]] = None,
107
+ context: dict[str, Any] | None = None,
108
108
  verify_context: bool = True,
109
109
  ) -> str:
110
110
  """
@@ -144,7 +144,7 @@ class ProviderTokenEncryption:
144
144
  "Token may have been tampered with or used for wrong user/provider."
145
145
  )
146
146
 
147
- return cast(str, data["token"])
147
+ return cast("str", data["token"])
148
148
 
149
149
  except InvalidToken as e:
150
150
  raise ValueError(
@@ -154,7 +154,7 @@ class ProviderTokenEncryption:
154
154
  raise ValueError(f"Decryption failed: {e}") from e
155
155
 
156
156
  def rotate_key(
157
- self, encrypted_token: str, new_key: bytes, context: Optional[dict[str, Any]] = None
157
+ self, encrypted_token: str, new_key: bytes, context: dict[str, Any] | None = None
158
158
  ) -> str:
159
159
  """
160
160
  Re-encrypt token with new key (for key rotation).
@@ -5,7 +5,7 @@ Pydantic models for security-related operations.
5
5
  """
6
6
 
7
7
  from datetime import datetime
8
- from typing import Optional
8
+
9
9
  from pydantic import BaseModel, Field
10
10
 
11
11
 
@@ -15,12 +15,12 @@ class ProviderTokenMetadata(BaseModel):
15
15
  user_id: str = Field(..., description="User ID who owns the token")
16
16
  provider: str = Field(..., description="Provider name (plaid, alpaca, alphavantage, etc.)")
17
17
  encrypted_token: str = Field(..., description="Encrypted token (base64-encoded)")
18
- key_id: Optional[str] = Field(None, description="Key ID for key rotation")
18
+ key_id: str | None = Field(None, description="Key ID for key rotation")
19
19
  created_at: datetime = Field(
20
20
  default_factory=datetime.utcnow, description="Token creation timestamp"
21
21
  )
22
- expires_at: Optional[datetime] = Field(None, description="Token expiration timestamp")
23
- last_used_at: Optional[datetime] = Field(None, description="Last time token was used")
22
+ expires_at: datetime | None = Field(None, description="Token expiration timestamp")
23
+ last_used_at: datetime | None = Field(None, description="Last time token was used")
24
24
 
25
25
 
26
26
  class PIIAccessLog(BaseModel):
@@ -30,8 +30,8 @@ class PIIAccessLog(BaseModel):
30
30
  pii_type: str = Field(..., description="Type of PII (ssn, account, card, etc.)")
31
31
  action: str = Field(..., description="Action performed (read, write, delete)")
32
32
  resource: str = Field(..., description="Resource accessed (e.g., user:123, account:456)")
33
- ip_address: Optional[str] = Field(None, description="IP address of requester")
34
- user_agent: Optional[str] = Field(None, description="User agent string")
33
+ ip_address: str | None = Field(None, description="IP address of requester")
34
+ user_agent: str | None = Field(None, description="User agent string")
35
35
  timestamp: datetime = Field(default_factory=datetime.utcnow, description="Access timestamp")
36
36
  success: bool = Field(True, description="Whether access was successful")
37
- error_message: Optional[str] = Field(None, description="Error message if failed")
37
+ error_message: str | None = Field(None, description="Error message if failed")
@@ -9,21 +9,21 @@ import re
9
9
  from typing import Any
10
10
 
11
11
  from .pii_patterns import (
12
- ACCOUNT_PATTERN,
13
12
  ACCOUNT_CONTEXT,
13
+ ACCOUNT_PATTERN,
14
14
  CARD_PATTERN,
15
- CVV_PATTERN,
16
15
  CVV_CONTEXT,
16
+ CVV_PATTERN,
17
17
  EIN_PATTERN,
18
18
  EMAIL_PATTERN,
19
19
  PHONE_PATTERN,
20
- ROUTING_PATTERN,
21
20
  ROUTING_CONTEXT,
22
- SSN_PATTERN,
23
- SSN_NO_DASH,
21
+ ROUTING_PATTERN,
24
22
  SSN_CONTEXT,
25
- luhn_checksum,
23
+ SSN_NO_DASH,
24
+ SSN_PATTERN,
26
25
  is_valid_routing_number,
26
+ luhn_checksum,
27
27
  )
28
28
 
29
29
 
fin_infra/settings.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from functools import lru_cache
4
+
4
5
  from pydantic import Field
5
6
  from pydantic_settings import BaseSettings, SettingsConfigDict
6
7
 
@@ -33,5 +34,5 @@ class Settings(BaseSettings):
33
34
 
34
35
 
35
36
  @lru_cache
36
- def get_settings() -> "Settings":
37
+ def get_settings() -> Settings:
37
38
  return Settings()
fin_infra/tax/__init__.py CHANGED
@@ -33,7 +33,7 @@ Example:
33
33
  import os
34
34
 
35
35
  from fin_infra.providers.base import TaxProvider
36
- from fin_infra.providers.tax import MockTaxProvider, IRSProvider, TaxBitProvider
36
+ from fin_infra.providers.tax import IRSProvider, MockTaxProvider, TaxBitProvider
37
37
  from fin_infra.tax.add import add_tax_data
38
38
  from fin_infra.tax.tlh import (
39
39
  TLHOpportunity,
fin_infra/tax/add.py CHANGED
@@ -17,7 +17,8 @@ Example:
17
17
  """
18
18
 
19
19
  from decimal import Decimal
20
- from fastapi import FastAPI, Query, Body
20
+
21
+ from fastapi import Body, FastAPI, Query
21
22
  from pydantic import BaseModel
22
23
 
23
24
  from fin_infra.providers.base import TaxProvider
@@ -89,8 +90,8 @@ def add_tax_data(
89
90
  >>> # POST /tax/tax-liability
90
91
  """
91
92
  # Use svc-infra user_router for authentication (tax data is user-specific and sensitive)
92
- from svc_infra.api.fastapi.dual.protected import user_router
93
93
  from svc_infra.api.fastapi.docs.scoped import add_prefixed_docs
94
+ from svc_infra.api.fastapi.dual.protected import user_router
94
95
 
95
96
  # Initialize provider
96
97
  if provider is None:
fin_infra/tax/tlh.py CHANGED
@@ -55,7 +55,7 @@ Cost Considerations:
55
55
 
56
56
  from __future__ import annotations
57
57
 
58
- from datetime import datetime, timezone
58
+ from datetime import UTC, datetime
59
59
  from decimal import Decimal
60
60
  from typing import TYPE_CHECKING
61
61
 
@@ -412,9 +412,9 @@ def _assess_wash_sale_risk(symbol: str, last_purchase_date: datetime | None) ->
412
412
  return "none"
413
413
 
414
414
  # Calculate days since last purchase
415
- now = datetime.now(timezone.utc)
415
+ now = datetime.now(UTC)
416
416
  if last_purchase_date.tzinfo is None:
417
- last_purchase_date = last_purchase_date.replace(tzinfo=timezone.utc)
417
+ last_purchase_date = last_purchase_date.replace(tzinfo=UTC)
418
418
 
419
419
  days_since = (now - last_purchase_date).days
420
420
 
@@ -506,8 +506,8 @@ def _generate_tlh_recommendations(
506
506
  recommendations = []
507
507
 
508
508
  # Timing recommendations
509
- now = datetime.now(timezone.utc)
510
- days_until_year_end = (datetime(now.year, 12, 31, tzinfo=timezone.utc) - now).days
509
+ now = datetime.now(UTC)
510
+ days_until_year_end = (datetime(now.year, 12, 31, tzinfo=UTC) - now).days
511
511
 
512
512
  if days_until_year_end < 30:
513
513
  recommendations.append(
fin_infra/utils/http.py CHANGED
@@ -1,8 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
- import httpx
4
3
  from typing import Any, cast
5
- from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
4
+
5
+ import httpx
6
+ from tenacity import retry, retry_if_exception_type, stop_after_attempt, wait_exponential
6
7
 
7
8
  _DEFAULT_TIMEOUT = httpx.Timeout(20.0)
8
9
 
@@ -17,4 +18,4 @@ async def aget_json(url: str, **kwargs) -> dict[Any, Any]:
17
18
  async with httpx.AsyncClient(timeout=_DEFAULT_TIMEOUT) as client:
18
19
  r = await client.get(url, **kwargs)
19
20
  r.raise_for_status()
20
- return cast(dict[Any, Any], r.json())
21
+ return cast("dict[Any, Any]", r.json())
fin_infra/utils/retry.py CHANGED
@@ -2,8 +2,8 @@ from __future__ import annotations
2
2
 
3
3
  import asyncio
4
4
  import random
5
- from typing import TypeVar
6
5
  from collections.abc import Awaitable, Callable, Iterable
6
+ from typing import TypeVar
7
7
 
8
8
  from fin_infra.exceptions import RetryError
9
9
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: fin-infra
3
- Version: 0.1.81
3
+ Version: 0.1.83
4
4
  Summary: Financial infrastructure toolkit: banking connections, market data, credit, cashflows, and brokerage integrations
5
5
  License: MIT
6
6
  Keywords: finance,banking,plaid,brokerage,markets,credit,tax,cashflow,fintech,infra
@@ -0,0 +1,180 @@
1
+ fin_infra/__init__.py,sha256=7oL-CCsALNifBODAn9LriicaIrzgJkmVPvE-9duP0mw,1574
2
+ fin_infra/__main__.py,sha256=1qNP7j0ffw0wFs1dBwDcJ9TNXlC6FcYuulzoV87pMi8,262
3
+ fin_infra/analytics/__init__.py,sha256=zjAOFkI9xjg76ozZStYBXEPNwIsioj5fUBltja5JLyc,2327
4
+ fin_infra/analytics/add.py,sha256=-iAqKdvf9t0gQjjo3uOO56qA_ei4omKYDOynxb4SZPI,12654
5
+ fin_infra/analytics/cash_flow.py,sha256=lH-J6RIUzcV9Fuy56i12N6vuIdPaGz-rhWquSgjkldU,10300
6
+ fin_infra/analytics/ease.py,sha256=aTAPc-Lmh6XP7REPVlAom38MtKCqeS-auNW-rpXRZJs,14282
7
+ fin_infra/analytics/models.py,sha256=cK6VKLZ763zXfn9REXOnLGx0v3Q8bUa-vH8aoNs2w-A,8215
8
+ fin_infra/analytics/portfolio.py,sha256=d39sZGa3TQVX1xN2nplPHuxhsE-rahuiyzd612DeZ_Y,26417
9
+ fin_infra/analytics/projections.py,sha256=T7LLG0Pe5f-WwgfDITdTMk-l8cCLZTM9cEC_Vxf6mkc,9154
10
+ fin_infra/analytics/rebalancing.py,sha256=VM8MgoJofmrCXPK1rbmVqWGB4FauNmHCL5HOEbrZR2g,14610
11
+ fin_infra/analytics/savings.py,sha256=n3rGNFP8TU5mW-uz9kOuqX_mDiVnDyAeDN06Q7Abotw,7570
12
+ fin_infra/analytics/scenarios.py,sha256=LE_dZVkbxxAx5sxitGhiOhZfWTlYtVbIvS9pEXkijLc,12246
13
+ fin_infra/analytics/spending.py,sha256=wCa8mhtdMTnI3eG9W28ljCgB_AQRVGxkrRA2ZwLi_RQ,26249
14
+ fin_infra/banking/__init__.py,sha256=6wwGNITzyehC9MBQc5jy0ewSTuNetyQu2AdND51O55w,22450
15
+ fin_infra/banking/history.py,sha256=BYvKLI_F198TBrtP7vMCCcBcszzFxZkmD-ClCezSVW8,10575
16
+ fin_infra/banking/utils.py,sha256=HhxZbeaA8zqVttgMiJGnShTo_r_0DaD7T3IMq8n8340,15252
17
+ fin_infra/brokerage/__init__.py,sha256=wJpgdOMWNxKt01eUIbu2oSmcFlL189nlWR0-PhLLVFc,17154
18
+ fin_infra/budgets/__init__.py,sha256=GgfujfgdVld6_yUf8bhkW-bsIXBLb4THlJMocVpA4mM,3986
19
+ fin_infra/budgets/add.py,sha256=i7Av--Z14sYQDJHETiF9VL71ouWBZcs3H3VZ62gqFEo,13508
20
+ fin_infra/budgets/alerts.py,sha256=KlK3r2qPzMw4naFMHsFjqkwKDxdj_2b_y-ofD1nldkg,9714
21
+ fin_infra/budgets/ease.py,sha256=vK5O8rvKzzJ1MUiwi7p9egayDFqyB23hPbbEhb1mhXE,8203
22
+ fin_infra/budgets/models.py,sha256=qd6bcjl2cOtFqRtNe1Xso_05cQlGG-4qhBkiTQKchy0,14335
23
+ fin_infra/budgets/scaffold_templates/README.md,sha256=FBtRSrQSkg7Xp8SPiuSmzGR94I2zzjOckb0_vKtcksY,14084
24
+ fin_infra/budgets/scaffold_templates/__init__.py,sha256=zQXi_vY4QS5a4Ddi2mVXMLM--rP021h5D94ohIC1dkU,172
25
+ fin_infra/budgets/scaffold_templates/models.py.tmpl,sha256=rpKhXwnx1gQjV_GGVqs8CvkFNHctrYcagC9swE14pVU,7553
26
+ fin_infra/budgets/scaffold_templates/repository.py.tmpl,sha256=khFgnQnVNnOo8DWYDmYz58MvdeSJpoS9QvTXcGhsa8g,10023
27
+ fin_infra/budgets/scaffold_templates/schemas.py.tmpl,sha256=x5gSQ7Kiuq08tum5joKmeY0ib2r3ekLKk09dFOl0PS0,5658
28
+ fin_infra/budgets/templates.py,sha256=Sbc7RcHXscq34g4t7J8OXM2Kfkt5DHuvqVnFU0Jiddc,12112
29
+ fin_infra/budgets/tracker.py,sha256=gF68a6sivdSfVDZanSwdGdhEcg6SEic0K_rO9ed7lvI,16460
30
+ fin_infra/cashflows/__init__.py,sha256=N9ZGKwIrQs-eiZZxqCow2aLBhW1MKcJoasQjGtyV6l4,8517
31
+ fin_infra/cashflows/core.py,sha256=YWvF0DVOfBkvO_MuDODjE-V_g52H2ixFRH_TjMXExDE,541
32
+ fin_infra/categorization/__init__.py,sha256=efLje12AW-ec9Vs5ynb41r4XCIWx5a-Z9WoGb3kQdIE,2030
33
+ fin_infra/categorization/add.py,sha256=-I-V7R8vWj2-B8yjtFn_pNryQV5uascFR18a1Ltcqm0,6247
34
+ fin_infra/categorization/ease.py,sha256=bomEtJAgwk9uiemNt1rk-IsTjJIhyJn0GJ_c58YEmJs,5836
35
+ fin_infra/categorization/engine.py,sha256=u1ZYDmuB0gZeJHn-CKvvwd7Z1HFiB-S91YuV_ZrK_Rc,12117
36
+ fin_infra/categorization/llm_layer.py,sha256=CSe6q-cKQgnKUKSItdDQwzMd8K1dsp-Mwua7SWZ9Ux0,12670
37
+ fin_infra/categorization/models.py,sha256=-rGXR0RW2EU_FQ7ZfDWBIXxx8QGJDxeBF9zKGYyVgqY,5931
38
+ fin_infra/categorization/rules.py,sha256=IpDnHBeuykRdu5vs3Lph4Y9-3RseIjjleQ5hZphQvNk,12849
39
+ fin_infra/categorization/taxonomy.py,sha256=p-tSOwJ0O-rFZ1LIlHSYdaYdSc65084j0fdMI_6LW84,13251
40
+ fin_infra/chat/__init__.py,sha256=-gufQz-rOZVXkcTUcCcXdG2oGL8csJBxwSuOMN_5aVc,6324
41
+ fin_infra/chat/ease.py,sha256=8T0BQUkWQVpaTooD5-ZtinackkciqGargXnzWzayj3M,3113
42
+ fin_infra/chat/planning.py,sha256=Vc3_58XxCnpT-347Q4BV0OY-xNINX79W7hFes4gou60,19915
43
+ fin_infra/cli/__init__.py,sha256=7M8gKULnui4__9kXRKRHgETuFwZlacK9xrq5rSZ31CM,376
44
+ fin_infra/cli/cmds/__init__.py,sha256=BvL3wRoUl3cO5wesv1Cqoatup7VeYMhq82tS19iNZHE,136
45
+ fin_infra/cli/cmds/scaffold_cmds.py,sha256=CDEg1Ak_2DT6iHtpMk2RfC-BUfP8zDNDA6Ekwa03Pl4,7574
46
+ fin_infra/clients/__init__.py,sha256=CL_NUNxLAKFvG7wL_F-rAhUucp6pm0sNHVtvCzVvLcw,708
47
+ fin_infra/clients/base.py,sha256=fZebDGIfQQybqeXpFpORlDZ6wSKf33aIAkUUpmyvZrA,979
48
+ fin_infra/clients/plaid.py,sha256=0_kV95vDgasbWyVQe3OEqtVXkF4Q6SNmvHwXXY0gzh8,816
49
+ fin_infra/compliance/__init__.py,sha256=KDEvTdpQOYYP8rlGerm78uKo4oH_VoWOK_4KL6IZNXI,5241
50
+ fin_infra/credit/__init__.py,sha256=cwCP_WlrG-0yb_L4zYsuzEsSalcfiCY9ItqXfD7Jx9E,6719
51
+ fin_infra/credit/add.py,sha256=8mYshzS8VGlnI_2b5WxXU5QFBrI-iEPfN1RDNz0apcA,8556
52
+ fin_infra/credit/experian/__init__.py,sha256=g3IJGvDOMsnB0er0Uwdvl6hGKKTOazqJxSDnB2oIBm0,761
53
+ fin_infra/credit/experian/auth.py,sha256=1TfT0wnqjAs-RCzDZKF_NH8LjTPDi8uMq7uyNPLJmS4,5612
54
+ fin_infra/credit/experian/client.py,sha256=jNvfiBM7Qn9w8J_ZqQReDa4ACymyoFVgopQpdznTI-o,8645
55
+ fin_infra/credit/experian/parser.py,sha256=7ptdLyTWWqHWqCo1CXn6L7XaIn9ZRRuOaATbFmMZZ64,7489
56
+ fin_infra/credit/experian/provider.py,sha256=a_BLyfc4wLUUqt8rkcbpHJuDB_DjFhS2kTZ-loVLdhM,13680
57
+ fin_infra/credit/mock.py,sha256=xKWZk3fhuIYRfiZkNc9fbHUNViNKjmOLSj0MTI1f4ik,5356
58
+ fin_infra/crypto/__init__.py,sha256=VTi2vjiDrlg0lU9H9tM3X-scRN-Z7QJ9UpdYIOeQcaw,8262
59
+ fin_infra/crypto/insights.py,sha256=cgMsjdrR7vOTKvEDbFCXpS7O7I8dMs1oz6cIbtrJWZI,11393
60
+ fin_infra/documents/__init__.py,sha256=Ub1hbX3PTrBSsBdcbL8PFf6oq8jSH4pYxW45-qOYPqs,1909
61
+ fin_infra/documents/add.py,sha256=2RSf_i39-JUT6c_jVsEQwW3FfQSlH4H9Z0t_H0vz86U,8091
62
+ fin_infra/documents/analysis.py,sha256=UWKTR_qXZoumItXUwHFMH3LAG2vFVlPITbIC8Y_r0s8,13970
63
+ fin_infra/documents/ease.py,sha256=z8hLaYhO1znBbcA9F10uNVa1BnH4rm3Jm5pexQwyiJY,9574
64
+ fin_infra/documents/models.py,sha256=RpazzhE9qBcTRk_NO7Dl_uvcHw9UpGtnpXFcJURMtYc,6865
65
+ fin_infra/documents/ocr.py,sha256=8I0XhiEdDhew55jUxOB5whoO5OcSXD71xiv8HhnyYno,9565
66
+ fin_infra/documents/storage.py,sha256=HXfubl-4PspvA-U8czB-4TgZKI1kOlw440jYHRDzjoY,10300
67
+ fin_infra/exceptions.py,sha256=k7L3vfXcONM2-AqmqNhQvOHobVBrLPTYp44cMUxuP3o,16951
68
+ fin_infra/goals/__init__.py,sha256=iiy7qkPazSSAmPFhy2EXkfJvOBfb7ymrqS1eXBNiaQc,2130
69
+ fin_infra/goals/add.py,sha256=zobcqEsEzsmd9itSPyPmzpkzFQYZlETo9d17bU9s3mc,20534
70
+ fin_infra/goals/funding.py,sha256=Fw6hUvb8yNWineEbRXFYgw4_ZRnGrBSChBjkb7Qozrs,9303
71
+ fin_infra/goals/management.py,sha256=nf1Es-rdQcp8bAM1FNWonX94CvGMBS1Nis4Q1CWgY0c,33868
72
+ fin_infra/goals/milestones.py,sha256=mQHDn9FXVI0HJ9qBHGW25HRwyBjp_MOxjDml7z2kgiw,9996
73
+ fin_infra/goals/models.py,sha256=5X0BddvK9FBsXMTXBQn8YFBNLtIbXue9a4VdLH3rWR8,10173
74
+ fin_infra/goals/scaffold_templates/README.md,sha256=CoE_3I2K32orOFH6CvfVBaJBTGDYIESd5-48V7vU1FI,9974
75
+ fin_infra/goals/scaffold_templates/__init__.py,sha256=rLFam-mRsj8LvJu5kRBEIJtw9rFUof7KApgD2IRE56c,107
76
+ fin_infra/goals/scaffold_templates/models.py.tmpl,sha256=b23Nlwm05MFMQE4qkrylTPXqulsN6cuFzNev2liY7DI,5714
77
+ fin_infra/goals/scaffold_templates/repository.py.tmpl,sha256=4BFy-fPBR412p8wb8VzsekxM3uGno-odqZP_BuMAXBU,11046
78
+ fin_infra/goals/scaffold_templates/schemas.py.tmpl,sha256=M1hS1pK9UDXcNqPW-NGu9804hTFe4FPdUDVgDSMcQl4,5331
79
+ fin_infra/insights/__init__.py,sha256=fFYymoAY2zd7eooE-RqyFifXB_J-vVkHjyMak7o4wnQ,3984
80
+ fin_infra/insights/aggregator.py,sha256=HtaJipSA-O_HVComBcyQdkGs6guoW81sYwRYHXGdBJI,10251
81
+ fin_infra/insights/models.py,sha256=xov_YV8oBLJt3YdyVjbryRfcXqmGeGiPvZsZHSbvtl8,3202
82
+ fin_infra/investments/__init__.py,sha256=DQJa32LdXspbtxydric-AfT3o5iDkqIByAsSriSfGak,6729
83
+ fin_infra/investments/add.py,sha256=UV2_99z1p8cUiifVFJXOF0lGd0ucMgZ5s9N7IFyE_NY,17193
84
+ fin_infra/investments/ease.py,sha256=d5ISfxpCius6JM2LZNReztW6-IizaqoxNU4aEbXWA74,9487
85
+ fin_infra/investments/models.py,sha256=UyOvtU1-uxrgE0zLP5WY3wpn3YOdOv6_b05oGismxNU,18412
86
+ fin_infra/investments/providers/__init__.py,sha256=V1eIzz6EnGJ-pq-9L3S2-evmcExF-YdZfd5P6JMyDtc,383
87
+ fin_infra/investments/providers/base.py,sha256=1plM-o_fV6jQyyPnpZT5q8ir96oyxvh0zwA3qpiVIFY,9810
88
+ fin_infra/investments/providers/plaid.py,sha256=X42cMpsHNcOPcYvl73jrP8x7nQ399n2_it3Ko9UIkI0,18751
89
+ fin_infra/investments/providers/snaptrade.py,sha256=Hs5uM3F31mGzSONgVXLlL2BR86mjOWs8OhcpLiUeaAo,23251
90
+ fin_infra/investments/scaffold_templates/README.md,sha256=PhgxfMLrro2Jz83b7XEnBi7lexiWKqlMrd2UU2Rbs8A,12149
91
+ fin_infra/investments/scaffold_templates/__init__.py,sha256=iR0oiAzXFYXHBnVJjaEnAzk6omncYOLg0TKMJ7xomBc,82
92
+ fin_infra/investments/scaffold_templates/models.py.tmpl,sha256=5inP5-jw-qEfPYxSN71tn4AojZ9PesOIeuHTw181N-c,5849
93
+ fin_infra/investments/scaffold_templates/repository.py.tmpl,sha256=XwOEpQZfuXut1WLiq-GSSvv0oX0iYCW54eJNL0Cav94,14656
94
+ fin_infra/investments/scaffold_templates/schemas.py.tmpl,sha256=knWmn-Kyr7AdgPD4ZPMb6T49ZuPXeuOMqmjYNyA0CA0,5451
95
+ fin_infra/markets/__init__.py,sha256=Ba9iUTfDkkla8GwPo3gULTJYUDQh5gSgGN15BxHINpo,9865
96
+ fin_infra/models/__init__.py,sha256=y94RJ_1-bzgNUCxqE76X56WIOk3-El_Jueqy7uB0rb8,860
97
+ fin_infra/models/accounts.py,sha256=ExQimE2O5dyugFMW7nCboWbWcaX3Nnl5Gg-B1XLSdIk,1138
98
+ fin_infra/models/brokerage.py,sha256=TV5KMe78e-ttjcUbZIfdGo3x0NisAQ3puwv_ehtgSHc,8312
99
+ fin_infra/models/candle.py,sha256=5JeqUvqlFfYE61uViBeLKZCh2wKdJZH7Pvi-TLzN4FI,536
100
+ fin_infra/models/credit.py,sha256=rSdSURsMe9_i2gxmwPTDwNQWOuM2zutL-OhvHsnbtmw,12144
101
+ fin_infra/models/money.py,sha256=63pdGD1WBMHicJ1w7pbU1g5fqt4gIzPuqQQ2-NSlBuc,401
102
+ fin_infra/models/quotes.py,sha256=-YBzgnjjCihRAprUdaPRtfwKrgliDIGgqAnaM69VbDU,521
103
+ fin_infra/models/tax.py,sha256=as40J9h24BB7LmeaIfay509UaYEctmk5CPW9CfcjWZc,15657
104
+ fin_infra/models/transactions.py,sha256=8C4taS9ZGLeFYGqG7JGkLq5ZinvAjHPLrKyRu_Sy5_0,791
105
+ fin_infra/net_worth/__init__.py,sha256=4LzVM2Y0OkBlZoD5FUAbLwtORp1okYcsYc4zj0P8C7k,3452
106
+ fin_infra/net_worth/add.py,sha256=QWfHIHJs2CV99WRBqjQ2OteiOrn5cR9nurmxTF9v5rg,23191
107
+ fin_infra/net_worth/aggregator.py,sha256=9Kx2vUR71QwqYZdGaCfmYrJ1hNxzd1EEuAdWJoNjqTI,12780
108
+ fin_infra/net_worth/calculator.py,sha256=SQJGJDok5HgvoAhKBxeeqt8vhGMchABU3zPmNRpqNy4,13139
109
+ fin_infra/net_worth/ease.py,sha256=ERdFrUjjb5l5BRp_c2tEfE1obTpRc_-FA9LnV7BTiEw,15883
110
+ fin_infra/net_worth/goals.py,sha256=BJGxdsMjvgQDELFEJo-ai3DvsAzUNXvzMXkwovHr8yQ,1238
111
+ fin_infra/net_worth/insights.py,sha256=LJ-EI0jQuBVqoFthgDq2PAmwRGorx0dP2Rsm4yNvquY,25221
112
+ fin_infra/net_worth/models.py,sha256=sZv3dGw5zwckE2XQ7n5ehK7sv4jdGCo9c2g4ZtZHwCI,26880
113
+ fin_infra/net_worth/scaffold_templates/README.md,sha256=Wqd6ksqFjmtNdDFOWVV_duuAcePWwiu3_YgkVM9N_WY,14363
114
+ fin_infra/net_worth/scaffold_templates/__init__.py,sha256=OKeMCC_JNw6m8rBWr_wesOIJ1OR9LCBeIkXKahbCGC4,132
115
+ fin_infra/net_worth/scaffold_templates/models.py.tmpl,sha256=9BKsoD08RZbSdOm0wFTbx5OzKfAEtuA1NcWyS1Aywx4,5934
116
+ fin_infra/net_worth/scaffold_templates/repository.py.tmpl,sha256=DSErnNxeAe4pWeefARRK3bU0hHltqdIFffENfVwdd7c,12798
117
+ fin_infra/net_worth/scaffold_templates/schemas.py.tmpl,sha256=VkFsxyZx4DFDhXDhn-7KT0IgrXCvgaS5ZdWbjyezWj0,4709
118
+ fin_infra/normalization/__init__.py,sha256=O-8YvPbKWgfdC6E2qzXuCFLJ6cM-CS8GmBO8TDcJ9X0,6246
119
+ fin_infra/normalization/currency_converter.py,sha256=uuu8ASa5ppEniWLEVEpiDxXjZzln9nopWrhrATcD6Z4,7058
120
+ fin_infra/normalization/models.py,sha256=gNC9chpbQPRN58V2j__VEPVNReO1N8jH_AHObwGPWu0,1928
121
+ fin_infra/normalization/providers/__init__.py,sha256=LFU1tB2hVO42Yrkw-IDpPexD4mIlxob9lRrJEeGYqpE,559
122
+ fin_infra/normalization/providers/exchangerate.py,sha256=I_2TK_LLOcYCy3HcN9Nut3UwqTWEOX26GktmX3cczvY,6340
123
+ fin_infra/normalization/providers/static_mappings.py,sha256=m14VHmTZipbqrgyE0ABToabVx-pDcyB577LNWrACEUM,6809
124
+ fin_infra/normalization/symbol_resolver.py,sha256=M7Li7LFiH4xpvxXcYQlJyk0iqgqpwaj6zQKsTzWZzas,8130
125
+ fin_infra/obs/__init__.py,sha256=kMMVl0fdwtJtZeKiusTuw0iO61Jo9-HNXsLmn3ffLRE,631
126
+ fin_infra/obs/classifier.py,sha256=JasWCqSkYjllJNZ5Gwbrd53ZhLwhYNZ0i2nbTcklEog,5155
127
+ fin_infra/providers/__init__.py,sha256=jxhQm79T6DVXf7Wpy7luL-p50cE_IMUbjt4o3apzJQU,768
128
+ fin_infra/providers/banking/base.py,sha256=KeNU4ur3zLKHVsBF1LQifcs2AKX06IEE-Rx_SetFeAs,102
129
+ fin_infra/providers/banking/plaid_client.py,sha256=8Nvd9Ow_v6Scnw79R86uSvRcBRHPgc3ytsQze50E7aM,6524
130
+ fin_infra/providers/banking/teller_client.py,sha256=733Eq-o9Yt7Sm_aWOeunJU4EWYRAaZNS7vgDVGqR0W4,10279
131
+ fin_infra/providers/base.py,sha256=Tqjl5_hSTShgYLrSiKzeDbnL_I-dji-G_itkumm15IM,7722
132
+ fin_infra/providers/brokerage/alpaca.py,sha256=X37cKou4jhekY-EHB4WKOa8K66Vkb4m5riDcuVdv7wc,9926
133
+ fin_infra/providers/brokerage/base.py,sha256=JJFH0Cqca4Rg4rmxfiwcQt-peRoBf4JpG3g6jx8DVks,106
134
+ fin_infra/providers/credit/experian.py,sha256=r7lpFecgOdNEhb_Lxz2Z-BG8R3p2n0XlqDKL7y8NZ-0,482
135
+ fin_infra/providers/identity/stripe_identity.py,sha256=JQGJRuQdWP5dWDcROgtz1RrmpkytRv95H6Fn-x1kifU,501
136
+ fin_infra/providers/market/alphavantage.py,sha256=nZPqATG2XMBHHg9Bcsn5wQhSMNLtFycnO_iASG7tCsM,8891
137
+ fin_infra/providers/market/base.py,sha256=ljBzZTfjYQS9tXahmxFic7JQSZeyoiDMUZ1NY0R7yto,108
138
+ fin_infra/providers/market/ccxt_crypto.py,sha256=pf9pxhsp0U4vP078gjkGwL6rutziLtdc8bpw0_ecA2c,1614
139
+ fin_infra/providers/market/coingecko.py,sha256=iAk7--tHaK1p1tAsTyO4foIJkg9RNdu5XioEnITqdxY,2667
140
+ fin_infra/providers/market/yahoo.py,sha256=rFM0eOKxkVrxFhfsHDUTkVzsx6hMUUl5f5lF_qZcW-8,5393
141
+ fin_infra/providers/registry.py,sha256=yPFmHHaSQERXZTcGkdXAtMU7rL7VwAzW4FOr14o6KS8,8409
142
+ fin_infra/providers/tax/__init__.py,sha256=buJkvFZNGxOXrCPXYBoRgWQUShqNsK9AjiCgPaVx4Lw,207
143
+ fin_infra/providers/tax/irs.py,sha256=SAh4mKYbSrGt5gZ1JgVsEzl1ZaHTve8DKEkblwoX8lI,4701
144
+ fin_infra/providers/tax/mock.py,sha256=-6VD9F3usfoxU-KqAj8jC3Q1xsnJ4o5ZT1W5Ze7X698,14442
145
+ fin_infra/providers/tax/taxbit.py,sha256=Lp3eH64oUrqwVT5P8oPxa01LFAmhhlfbquDFiiiDcz8,4271
146
+ fin_infra/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
147
+ fin_infra/recurring/__init__.py,sha256=lYeMdpgxq52x7siFp62_xVqzUx84vMNKrTuiaT2JTi4,2308
148
+ fin_infra/recurring/add.py,sha256=Kc5Wv-4XshS8ET1wuydDJfRz6fQAkbZ2uQ1qFAJ0X5w,19055
149
+ fin_infra/recurring/detector.py,sha256=MCq_48V6o9Ig9lTTHM054KNh2I_udEjWBmV_iF361ac,20131
150
+ fin_infra/recurring/detectors_llm.py,sha256=MB9hGUTo8WEa-lpevOkrp0OQOXnatskzW02l_EfwTPo,11486
151
+ fin_infra/recurring/ease.py,sha256=8t0lXMqNxHZkO0fw29sEn_lQjitDq0UxebtqA74tag0,11157
152
+ fin_infra/recurring/insights.py,sha256=-SgskqHqOlkDwCfj4NsPMwlq1bHY2J5gM-1c_t0bSv0,15853
153
+ fin_infra/recurring/models.py,sha256=o0N8G-QhVb4zILEyry6M1VZ7liFJIOHwlejvn6p4K8M,8894
154
+ fin_infra/recurring/normalizer.py,sha256=mihqV84Dd5AJ9JYU6KW3W8nH3TCU8FiKpPicipuClPM,9760
155
+ fin_infra/recurring/normalizers.py,sha256=4DGy0RGHz5NameRpZC-QYbS2PkZc9UqjtjTuVQ_OJHA,15914
156
+ fin_infra/recurring/summary.py,sha256=wQshznaswIbGUPIMyayubRcRfUvVNBtyzmYx50-nqs0,14621
157
+ fin_infra/scaffold/__init__.py,sha256=IfL_CHHMpQB1efqY37BlIu07356tLaeVI2Mv3C0qYDs,827
158
+ fin_infra/scaffold/budgets.py,sha256=qLnyPh-a-ZrslstaxRtR__Bpwlz0EncSdVnCM7fDBI4,9481
159
+ fin_infra/scaffold/goals.py,sha256=C1mexWRbWV3aRdmiT65LpKMMWzhTWTX_upeCcsjTcWw,9684
160
+ fin_infra/security/__init__.py,sha256=wM341EZioKtfTawpFCciaFh0FlpHHkoEoviW9pGYqpI,1363
161
+ fin_infra/security/add.py,sha256=Y_XXNd-FTpSaHmO4xkYvkW4CLlFGCuQWe9gJ7WuwiLY,2746
162
+ fin_infra/security/audit.py,sha256=TekYWCOUT9Sf1sDS2-EEREtW7nhWo3H7iaLVbLPx308,3322
163
+ fin_infra/security/encryption.py,sha256=Cr_9xhBiUvYx1tDjCiLTzyY9NRTlqljWGgswqXT499Y,6139
164
+ fin_infra/security/models.py,sha256=s8dsvpxP-7DThUZl3Fvr3S6KVAfL5r3TKcd4uj_hCTE,1689
165
+ fin_infra/security/pii_filter.py,sha256=nVqzbG_-Z6m8fzzS1KBy9yFwaZ8eRrU00Q72fSkVyU8,8307
166
+ fin_infra/security/pii_patterns.py,sha256=SM-o7cL6NdgkOmtBedsN2nJZ5QPbeYehZdYmAujk8Y8,3070
167
+ fin_infra/security/token_store.py,sha256=qgxhBKwhtVpchyHv30mM-cttuGZlzZvZLC4Oa-gTTeg,6075
168
+ fin_infra/settings.py,sha256=11JgIhjGwWnwixV-hveEWpoWd_JC0ixLnOQoLWCiwNo,1387
169
+ fin_infra/tax/__init__.py,sha256=U0EUKQwbDqnAYwU8WRx6AD07TaB-ELdKGISOQ-904lw,6103
170
+ fin_infra/tax/add.py,sha256=dYigcgQFEP38NLoNuhh7vpSoy07sWX6Z_DTp1tWFJXw,14553
171
+ fin_infra/tax/tlh.py,sha256=3khtiEkGKIIHi2mbMM0ss-GKQ8vM3FS6hly8R00qseY,21482
172
+ fin_infra/utils/__init__.py,sha256=gKacLSWMAis--pasd8AuVN7ap0e9Z1TjRGur0J23EDo,648
173
+ fin_infra/utils/http.py,sha256=rDEgYsEBrEe75ml5RA-iSs3xeU5W-3j-czJlT7WbrM4,632
174
+ fin_infra/utils/retry.py,sha256=YiyTgy26eJ1ah7fE2_-ZPa4hv4bIT4OzjYolkNWb5j0,1057
175
+ fin_infra/version.py,sha256=4t_crzhrLum--oyowUMxtjBTzUtWp7oRTF22ewEvJG4,49
176
+ fin_infra-0.1.83.dist-info/LICENSE,sha256=wK-Ya7Ylxa38dSIZRhvNj1ZVLIrHC-BAI8v38PNADiA,1061
177
+ fin_infra-0.1.83.dist-info/METADATA,sha256=X4R2GNABxoN7u8D1d90fXL8XWlJwnyFUaprYaAW6s9o,10479
178
+ fin_infra-0.1.83.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
179
+ fin_infra-0.1.83.dist-info/entry_points.txt,sha256=Sr1uikvALZMeKm-DIkeKG4L9c4SNqysXGO_IRF8_9eU,53
180
+ fin_infra-0.1.83.dist-info/RECORD,,