Changelog
Alle nennenswerten Änderungen an API, SDKs und MCP-Server.
Versionierungs- & Deprecation-Politik
Die /v1-API ist stabil: Felder werden nur hinzugefügt, innerhalb von v1 nie umbenannt oder entfernt. Breaking Changes erschienen als neuer Major-Pfad (/v2) mit mindestens 6 Monaten Parallelbetrieb, angekündigt hier und per E-Mail an aktive Schlüsselinhaber. Das Projekt folgt Semantic Versioning.
Changelog
All notable changes to IBANforge are documented here. The format follows Keep a Changelog and the project adheres to Semantic Versioning.
[Unreleased]
Added
- Full BBAN structural validation (all 89 countries) —
/v1/iban/validatenow enforces the SWIFT IBAN Registry character structure of the BBAN on top of length + mod-97.DE17ABCDEFGH1234567890(letters inside Germany's all-numeric bank code, mod-97-valid) is finally rejected with an agent-friendlyinvalid_bban_structuredetail naming the field, the position and the expected charset. Check digits00/01/99(outside the ISO 13616 range 02–98) and non-numeric check digits are rejected asinvalid_check_digits—CH99…used to validate. Patterns are cross-checked against three sources (registry Release 101 via python-stdnum, schwifty, ibantools — 8 ibantools divergences resolved against the registry) and precompiled at module load (hot path unchanged, ~0.0015 ms). A registry-conformance suite validates all 89 official sample IBANs to guard against over-rejection. - BBAN decomposition for the 47 missing countries (incl. SEPA members BG, RO, IS): they previously returned an empty
bank_code, silently disabling BIC lookup, issuer classification andrisk_indicators./v1/iban/structure/:countrynow exposes per-field SWIFT charsets (4!a,8!n…), the fullbban_pattern, and an official example IBAN for every country (was 26). - Explicit paywall cause in 402 responses — when a request falls through to the paywall because of an exhausted monthly quota, used-up credit bundle or invalid/revoked API key, the 402 body now carries a
causeobject (reason,detail, plus quota/credits numbers) and a message stating the real situation, instead of the generic "authentication or payment required" that reads as "you are anonymous" to an authenticated client. NewX-API-Key-Invalidheader on the broken-key path. +3 integration tests. (Micro-audit conversion 2026-07-03: a trial user dying silently on the quota wall is invisible churn.) - MCP npm package 1.3.2 tells the truth on degraded results — the stdio package now relays the 402
causein its_hint, labels quota/credits/key-caused fallbacks asDEGRADED RESULT(instead of the misleading "Anonymous mode" when a key is configured), no longer masks an invalid-IBAN 400 behind a "payment required" message, and stops promising that an API key raises the per-IP rate limit (it does not). - Self-service API-key lifecycle —
POST /v1/keys/revoke(kill a leaked key, idempotent) andPOST /v1/keys/rotate(mint a fresh key that atomically inherits the email, monthly limit and remaining credits, then deactivates the old one). +7 regression tests. - TypeScript SDK test suite — 25 Vitest specs (mocked
fetch): base-URL normalization, Bearer-auth headers, request shapes,validateBatchinput guards, full HTTP-status → typed-error mapping (401/403/402/429-quota/429-rate/4xx/5xx), timeout/network wrapping, and theusage()no-key precondition. The SDK previously had zero tests. Both SDK suites now run in CI on every push. - Monthly Swiss-clearing refresh — the
ch_clearingtable (SIX BankMaster) is now reseeded and committed by the existing monthly database cron, in the same workflow as the BIC database (both live indata/bic.sqlite, so one workflow / one commit avoids a same-file race).
Changed
- Bank-level sanctions are now built from primary sources — OFAC SDN (US public domain) as the spine, with EU / UN / SECO consolidated lists best-effort — removing the runtime dependency on the CC-BY-NC OpenSanctions dataset. Country-level FATF/sanctions signals are unchanged. Net effect on BIC8 indicators: identical coverage minus one entity.
Fixed
- Batch validation now bills 1 credit per IBAN on API keys — a
/v1/iban/batchcall of N IBANs debits N free-tier requests or N prepaid credits. Previously a whole batch billed a single unit, so a 100-IBAN batch cost the same as one validation — a ~100× underbilling that x402 callers never got (the x402 price was already $0.002 × N). Billing is all-or-nothing: a batch that exceeds the remaining allowance is refused with a machine-readable 402 naming the shortfall (credits_insufficient/monthly_quota_insufficientcauses,X-Credits-Required+X-Credits-Remaining/X-Quota-Required+X-Quota-Remainingheaders) and nothing is consumed; handler-level 4xx rejections refund the full pre-charge. Successful multi-unit charges are surfaced viaX-Credits-Charged/X-Quota-Charged. Bundle descriptions now say "credits" instead of "calls" across the OpenAPI spec, x402 discovery metadata and llms.txt, and the batch's "10x cheaper" claim is corrected to the real 2.5× ($0.002 vs $0.005 per IBAN). - Russia FATF status was 'member' — factually wrong since its suspension on 24 Feb 2023. New
suspendedstatus (surfaced as-is insanctions.fatf_status), scored at least as severely as non-membership (+10,fatf_suspendedflag). FATF lists synced to the 17–19 June 2026 plenary: grey list +BA +IQ / −DZ −NA (22 jurisdictions), black list unchanged,fatf_as_of→2026-06. - Compliance under-scored countries without a BBAN structure — country risk was read from
risk_indicators(absent when BBAN parsing failed) and silently fell back tostandard: production RU scored 60/high without the country flag. The country-risk axis is now derived straight from the country code; RU answers ≥80/critical withhigh_risk_country+sanctioned_country+fatf_suspended. - Revolut LT IBANs answered
sct:false, no_vop— Revolut Bank UAB is EPC-registered underRVUALT2Vwhile its customer IBANs resolve to BICREVOLT21; the BIC8 join missed the membership. Documented EMI-alias step (refresh script + data): REVOLT21 now reports SCT / SCT_INST / SDD / VoP-ready. Wise (TRWIBEB1/TRWIGB22), N26 (NTSBDEB1) and Bunq (BUNQNL2A) verified already present under their IBAN-facing BICs. - 188/189 EBA STEP2 BIC entries had
found:true, institution:null— the seed read the XLSX 'Comment' column instead of the institution-name column. Seed fixed and all 188 names backfilled from the official EBA file (e.g.ATPIITM7XXX→ "A-Tono Payment Institute"); zero nameless entries remain across all sources. - QR-IID lookups were semantically inverted —
GET /v1/ch/clearing/30000answerediid:"30000", qr_iid:"9000". BankMaster QR rows (range 30000–31999) carry the institution's standard IID in their QR-IID column; the lookup now presentsiid= standard IID (09000),qr_iid= the queried QR-IID (30000), plusis_qr_iid: trueand an explanatory note. Standard-IID lookups are byte-identical to before; QR-IBAN enrichment gains the same corrected semantics. - Spoof-resistant client-IP extraction — rate-limiting and stats now read
x-real-ip(or the last, trusted-proxy hop ofX-Forwarded-For) instead of the attacker-controlled first segment, so a forgedX-Forwarded-Forcan no longer rotate around the rate limiter. Single shared extractor (extractClientIp) used by both call sites. - Swiss-clearing seed sanity floor —
seed-bc-nummer.tsaborts before droppingch_clearingif the SIX BankMaster feed returns fewer than 800 rows, so a truncated download can never wipe the ~1190-row table under the unattended cron.
Notes
- Two audit findings were investigated and confirmed false positives (no change, now documented in code):
qr_iidis a genuinely distinct allocation column (not a copy of the clearing IID), andgetCountryRiskis a deliberately separate AML axis that stacks on top of the DB FATF/sanctions signal — re-deriving it from the FATF table would downgrade sanctioned/grey-listed country scores.
[1.3.2] — 2026-06-03
Fixed
- Python SDK now ships its
py.typedmarker (PEP 561). The package already advertisedTyping :: Typed, but without the marker file downstreammypy/pyrightsilently ignored the inline type hints.pip install -U ibanforge(≥ 1.3.2) now gives type-checked autocompletion and signature checking. Python SDK only — the API, npm SDK and MCP server are unchanged at 1.3.1.
[1.3.1] — 2026-05-30
Fixed
- Broken copy-paste SDK examples on
/agents— corrected field names to the real response shape (bank_name,sepa.member,risk_indicators.country_risk,compliance.risk_score/risk_level,validateIban(iban)), plus stale country counts. - Coherence pass — every remaining "75+ countries" string aligned to the real 89 (layout meta in 3 languages, OG image, landing FAQ/meta/H3, blog articles, footer version, published MCP enum).
Changed
- Frontend: wired the free-key modal end-to-end, lead with the Swiss / MCP USP, 3-rail pricing.
/fr/famillereworked into a clear, illustrated FAQ.- Release process — hybrid procedure documented (
RELEASING.md): PyPI + MCP Registry publish automatically (MCP via GitHub Actions OIDC), npm publishes manually behind the 2026 npm 2FA approval gate;mcp-publisherinstalled from its release binary. - TypeScript SDK published as
@ibanforge/sdkwith corrected package metadata and an accurate README.
[1.3.0] — 2026-05-29
Added
- BBAN structure for LT, EE, LV, MT, CY — revives EMI / virtual-IBAN detection in those jurisdictions.
- EBA Clearing STEP2 SCT as an official SEPA reachability source (+201 BICs); EMI classification extended via the EBA / FCA registers.
- Compliance transparency — every response now discloses scope, a disclaimer, and data-freshness metadata.
- Discovery surfaces —
/agents.txtplain-text index,agent.jsonandmcp.jsonpath aliases, regeneratedllms.txt/mcp.jsonto 1.3.0 truth. - Stripe Checkout credit-pack rail + success page that retrieves the API key once.
Changed
- Hardened the compliance enrichment pipeline (primary-source ingestion).
- Aligned tool schemas and prices across all three MCP surfaces (stdio, HTTP, card).
Fixed
- Flag
XX-country BICs as test BICs; cap oversized IBAN input. - Corrected bank-code drift against the SWIFT IBAN Registry.
- Correctness, data-accuracy and SDK-parity fixes surfaced by the 4.8 multi-agent audit.
[1.2.0] — 2026-04-29
Added
- PyPI Python SDK
ibanforge1.1.0 —pip install ibanforge. Sync (IBANforge) + async (AsyncIBANforge) clients, 6 endpoints (format_iban,validate_iban,validate_batch,lookup_bic,lookup_ch_clearing,check_compliance), 1-line free key generator (IBANforge.generate_api_key("you@example.com")), TypedDict response shapes, 6 typed exception classes (AuthError, PaymentRequiredError, QuotaExhaustedError, RateLimitError, InvalidInputError, APIError, IBANforgeError), 16 respx-mocked tests, MIT license. https://pypi.org/project/ibanforge/ - Free
GET /v1/iban/formatendpoint — pure mod-97 + structure check, no DB hits, no API key, no quota. Returns valid/invalid + bban breakdown +upgrade_to_full_validationhint pointing to the paid/v1/iban/validate($0.005). Lets agents pre-filter malformed IBANs before paying for full enrichment. - Glama containerized release —
mcp/Dockerfile(two-stage, Node 20-slim, non-root user) registered on https://glama.ai/mcp/servers/cammac-creator/ibanforge. Server Coherence ✅ unlocked, Tool Definition Quality scanning enabled, badge upgrade D → A pending. /agentspage (EN/FR/DE) — agent-first integration guide with 3 paths (MCP, free key, x402)/openapipage — interactive Scalar API reference (try-it-out, codegen)- 6 JSON-LD schemas at the layout level (SoftwareApplication, Organization, FAQPage, HowTo, BreadcrumbList, WebAPI) for richer agent + SEO discovery
- Design tokens ported from the previous Vite version:
--ink-0..5,--fg-1..5,--amber-50..700,--swiss-500/600,--risk-{low,med,high},--syn-*,pulse-liveandblinkanimations,.eyebrow,.kv-grid,.endpoint-row,.tnum,.tracking-capsutility classes - Reusable components:
StatusDot,RiskChip,EndpointRow,ApiKeyDialogwith provider - Per-locale
<title>,<meta description>,<html lang>,hreflangalternates (EN/FR/DE) - Compliance-bundle endpoint
POST /v1/iban/compliance($0.02) advertised in pricing, calculator, landing - 5th endpoint
GET /v1/ch/clearing/:iid($0.003) advertised in pricing, calculator, landing - Persistent volume declaration in
railway.tomlforstats.sqlite(api keys, quotas, revenue) - WAL mode + busy_timeout + 5 missing indices on
stats.sqlitefor concurrent throughput - Permissions-Policy header denies camera/microphone/geolocation/payment/usb
- Content-Security-Policy on HTML responses (landing, MCP card)
IBANFORGE_FREE_MODEenv flag for explicit production free mode (loud warning)- Trust signals appended to all 5 paid 402 descriptions (production status, p99 latency, dataset size, version) — agents that filter on description quality reward this
outputSchemawith bare-output examples on every accept entry (CyberSapper recipe from CDP Discord) — unblocks CDP catalog + agentic.market indexing
Changed
ensureWalletConfigurednow fail-closes in production: missingX402_ENABLEDorWALLET_ADDRESStriggers a boot crash instead of silent fail-open- API-key middleware: when monthly quota is exhausted, the request now falls through to the x402 middleware (advertises payment requirements) instead of returning a hard 429 dead-end. Agents can keep using IBANforge by paying per call.
- Dashboard auth refactored:
SESSION_SECRETis now a distinct env var (not the password), session token includes a signediat, comparison is timing-safe - CORS_ORIGIN must be explicit in production (no wildcard); boot crashes if missing or
* - Frontend
nextupgraded 16.2.2 → 16.2.4 (fixes high-severity DoS advisory in Server Components) - Backend
npm audit fixresolves transitive postcss/hono path-traversal advisories
Fixed
- Per-locale metadata was being overridden on the home route by a static EN export — removed the override so
/frand/denow serve localized titles + descriptions <html lang>was alwaysenregardless of locale- 30+ hardcoded user-visible strings (Copy/Copied in code blocks, uptime tooltips, locale-aware date formatting in monitoring) now go through
next-intl - 2 blocking ESLint errors (setState-in-effect, JSX-in-try/catch) resolved
- Stale dashboard rate-limit comment clarifies per-Lambda scope
Security
- New
SESSION_SECRETrequirement for dashboard cookies (independent of password) - Constant-time login response delays prevent timing-attacks
- CSP + Permissions-Policy on HTML
- Strict CORS in production
Operational
The website is now served by the Next.js project (Vercel project ibanforge, repo subfolder frontend/). The previous Vite design-system project (ibanforge-design-system) is orphaned (no domain attached) and can be archived after a 30-day rollback window.
Migration notes
For self-hosted deployments:
- Set
SESSION_SECRETin production (openssl rand -hex 32) - Set
CORS_ORIGINto an explicit comma-separated list of your origins - Verify the Railway volume is mounted at
/app/data(boot logs warn if not) - To run in explicit free mode in production, set
IBANFORGE_FREE_MODE=true
Das Changelog wird auf Englisch geführt.