4.9 KiB
4.9 KiB
Tasks: enterprise-currency-providers
Change ID: enterprise-currency-providers
Package: @suaveplan/currency-providers
Target path: finance/currency/currency-providers
Prerequisites on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/currency, @suaveplan/retry, @suaveplan/logger
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- Create full directory tree per
proposal.mdlayout. package.jsonat0.1.0,"sideEffects": false, exports"."+ per-provider subpaths +http/fetch-wrapper+http/coalesce+wrappers/rate-limited.- Deps: workspace + catalog deps as listed in proposal.
- DevDeps:
vitest catalog:testing,@vitest/coverage-istanbul catalog:testing,@suaveplan/testing workspace:^. tsconfig.jsonextendinglibrary.json;vitest.config.tswithcreateTestConfig().- Scripts:
lint,typecheck,test,test:coverage,build,docs:check.
2. Types and errors
- Define
ApiKeyConfig,NoKeyConfig,HttpFetchOptions,RateLimitOptionsinsrc/types/provider.types.ts. - Write
provider.types.md(≥200 words). src/error-codes.ts:CURRENCY_PROVIDER_AUTH_FAILED,CURRENCY_PROVIDER_RATE_LIMITED,CURRENCY_PROVIDER_NETWORK_ERROR,CURRENCY_PROVIDER_PARSE_FAILED; implementProviderError/AuthError/RateLimitError/NetworkError/ParseErrorhierarchy;registerCurrencyProviderErrorCodes(); eager call.
3. HTTP utilities
- Implement
FetchWrapperinsrc/http/fetch-wrapper/fetch-wrapper.ts:request(url, init, options): addAbortSignaltimeout; parseX-RateLimit-*headers; on 401 throwAuthError; on 429 throwRateLimitErrorwithretryAfterMs; on network error throwNetworkError. Wrap with@suaveplan/retry.- OTel span per request with provider name, URL, status.
- Write
fetch-wrapper.test.ts: 200 success; 401 AuthError; 429 RateLimitError with header; timeout; retry. - Write
fetch-wrapper.md(≥200 words). - Implement
coalesceinsrc/http/coalesce/coalesce.ts: per-key in-flight dedup usingMap<string, Promise<T>>. - Write
coalesce.test.ts: concurrent calls to same key share one promise; different keys independent. - Write
coalesce.md(≥200 words).
4. Provider implementations
For each of the nine providers (EcbProvider, FixerProvider, OpenExchangeRatesProvider, BinanceProvider, CoinGeckoProvider, CoinMarketCapProvider, CryptoCompareProvider, KrakenProvider, VirtualCurrencyProvider):
- Implement the provider class implementing
CurrencyProvider. - All HTTP calls use the shared
FetchWrapper. - Parse upstream response via Zod schema; throw
ParseErroron mismatch. isHealthy(): returnfalsewhen circuit is open (delegated to the circuit breaker in@suaveplan/currency).- Write unit test using
vi.stubGlobal('fetch', ...)with a recorded response fixture: happy path + auth error + rate limit + parse error. - Write
.mddoc (≥200 words, API reference, auth setup, rate limits documented).
5. RateLimitedProvider wrapper
- Implement
RateLimitedProviderinsrc/wrappers/rate-limited-provider/: wraps a provider, enforces per-second QPS using a token-bucket; delays calls that exceed the limit; honoursRetry-AfterfromRateLimitError. - Write
rate-limited-provider.test.ts: QPS enforcement; Retry-After propagation. - Write
rate-limited-provider.md(≥200 words).
6. Integration tests
tests/integration.test.ts: skip unlessRUN_CURRENCY_LIVE=1. EcbProvider fetches real rates (no API key). Assert at least USD and EUR rates are positive and sane.
7. Docs + verify + publish
- Root
README.md: provider comparison table (auth, fiat/crypto, rate limit), quick-start with ECB, API table. bunx turbo lint --filter=@suaveplan/currency-providers— zero errors.bunx turbo typecheck --filter=@suaveplan/currency-providers— zero errors.bunx turbo test --filter=@suaveplan/currency-providers— all pass.bunx turbo test:coverage --filter=@suaveplan/currency-providers— 100%.bun scripts/publish.ts --package @suaveplan/currency-providers.- Update
CLAUDE.md; archive toopenspec/archive/2026-04-24-enterprise-currency-providers/.