Coverage for apps/integrations/catalog.py: 100%

15 statements  

« prev     ^ index     » next       coverage.py v7.17.0, created at 2026-11-04 14:06 +0000

1"""Code-level provider catalog (design D1). 

2 

3The *set of supported providers* (with category + scope) is a small, stable code constant tied 

4to the adapters. What a tenant *configures* — enable flags, org/user creds — lives in the DB 

5(`OrgIntegration`, `UserCredential`). Global platform integrations (Stripe/Twilio/SendGrid/ 

6Cognito/S3/reCAPTCHA) are NOT here — they stay env-configured (design D4). 

7""" 

8 

9from __future__ import annotations 

10 

11from dataclasses import dataclass 

12 

13PER_ORG = "per_org" 

14PER_USER = "per_user" 

15 

16 

17@dataclass(frozen=True) 

18class ProviderDef: 

19 code: str 

20 category: str # credit | aus | docmagic | lender | zapier | tireless 

21 scope: str # per_org | per_user 

22 label: str = "" 

23 

24 

25PROVIDERS: dict[str, ProviderDef] = { 

26 "meridianlink": ProviderDef("meridianlink", "credit", PER_USER, "MeridianLink Credit"), 

27 "du": ProviderDef("du", "aus", PER_USER, "Fannie Mae Desktop Underwriter"), 

28 "lpa": ProviderDef("lpa", "aus", PER_USER, "Freddie Mac Loan Product Advisor"), 

29 "docmagic": ProviderDef("docmagic", "docmagic", PER_ORG, "DocMagic Disclosures"), 

30 "zapier": ProviderDef("zapier", "zapier", PER_ORG, "Zapier Automations"), 

31 # Tireless AI is just another provider in the catalog (ADR-001): the connection ships last. 

32 "tireless": ProviderDef("tireless", "tireless", PER_ORG, "Tireless AI Processing"), 

33} 

34 

35 

36def get_provider(code: str) -> ProviderDef | None: 

37 return PROVIDERS.get(code) 

38 

39 

40def providers_by_category(category: str) -> list[ProviderDef]: 

41 return [p for p in PROVIDERS.values() if p.category == category]