# Provider Abstraction Pattern
Every external dependency is behind a TypeScript interface. Swapping a provider
is a one-file change in `src/app/composition-root.ts`.
```mermaid
flowchart TB
subgraph Core[Core Logic - No Provider Dependencies]
PE[Pipeline Orchestrator]
SE[Scoring Engine]
TG[Trademark Gate]
PM[Portfolio Manager]
end
subgraph Interfaces[Provider Interfaces]
DNS[DnsProvider]
RDAP[RdapProvider]
WHOIS[WhoisProvider]
TM[TrademarkProvider]
KW[KeywordProvider]
CP[CompsProvider]
REG[RegistrarProvider]
end
subgraph Community[Community Edition Implementations]
UR[UnboundResolver
+ NodeDnsFallback]
PR[PublicRdapProvider
+ FailoverRdapProvider]
NW[NodeWhoisProvider]
UP[UsptoCasesProvider
+ TsdrTrademarkProvider]
EP[EuipoProvider]
MK[ManualKeywordProvider
(local JSON)]
GS[GoogleSuggestKeywordProvider]
MC[ManualCompsProvider
(local CSV)]
MR[ManualRegistrarProvider]
WB[CdxProvider
(Wayback history)]
end
subgraph Optional[Optional Paid Implementations]
GA[GoogleAdsProvider
(needs Google Ads credentials)]
NB[NameBioProvider
(needs NameBio API access)]
CF[CloudflareRegistrarProvider
(only real registrar adapter)]
end
subgraph CrossCutting[Cross-Cutting Decorators]
CACHED[CachedProvider
(configurable TTL)]
RETRY[RetryingProvider
(exponential backoff + jitter)]
RATE[RateLimiter
(token bucket)]
CIRCUIT[CircuitBreaker
(max failures / time window)]
FAILOVER[FailoverRdapProvider
(primary → fallback)]
end
Core -.-> Interfaces
Interfaces --> Community
Interfaces --> Optional
Interfaces --> CrossCutting
CrossCutting --> Community
CrossCutting --> Optional
style Core fill:#1a1a2e,stroke:#0f3460,color:#eee
style Interfaces fill:#16213e,stroke:#533483,color:#eee
style Community fill:#0f3460,stroke:#16213e,color:#eee
style Optional fill:#1a1a2e,stroke:#16213e,color:#ddd
style CrossCutting fill:#2d1b69,stroke:#533483,color:#eee
```
Only two registrar adapters exist: `ManualRegistrarProvider` (no-op) and
`CloudflareRegistrarProvider`. The other marketplace adapters (Afternic,
Sedo, Dan.com, GoDaddy Auctions) were removed in v1.1.0 because they were
never verified against the vendors' APIs — see
[ADR-0082](../adr/0082-removal-of-unimplemented-features.md). They return
when API access exists.
## Wiring in Composition Root
All providers are wired in a single file: `src/app/composition-root.ts`.
```typescript
// Community edition wiring
const euipoTmProvider = new CachedTrademarkProvider(
new RetryingTrademarkProvider(
new EuipoProvider({
clientId: config.EUIPO_CLIENT_ID,
clientSecret: config.EUIPO_CLIENT_SECRET,
authUrl: config.EUIPO_AUTH_URL,
apiUrl: config.EUIPO_API_URL,
pageSize: config.EUIPO_PAGE_SIZE,
maxPages: config.EUIPO_MAX_PAGES,
rateLimiter: euipoRateLimiter,
}),
{},
euipoCircuitBreaker,
),
providerCacheRepo,
'EUIPO',
config.TM_CACHE_TTL_DAYS,
config.PROVIDER_MEMORY_CACHE_SIZE,
);
```