Skip to content

Add HKCCS, HKVPP and HKIPZ SEPA credit transfer segments#27

Open
tanacosa wants to merge 1 commit into
robocode13:mainfrom
tanacosa:feat/sepa-credit-transfer-segments
Open

Add HKCCS, HKVPP and HKIPZ SEPA credit transfer segments#27
tanacosa wants to merge 1 commit into
robocode13:mainfrom
tanacosa:feat/sepa-credit-transfer-segments

Conversation

@tanacosa

@tanacosa tanacosa commented Jun 14, 2026

Copy link
Copy Markdown

What

Registers three SEPA credit-transfer segments as first-class built-ins:

  • HKCCS — Einreichung SEPA-Überweisung (single SEPA credit transfer)
  • HKVPP — pain.002 status-report descriptor that must precede HKCCS
  • HKIPZ — SEPA Instant / SCT Inst ("Echtzeitüberweisung")

The README currently notes "No support for payment transactions or transfers yet"; these are the minimum writable payment segments for FinTS PIN/TAN. The change is additive: 3 new files + 3 lines in registry.ts. Nothing existing changes.

Why built-ins

The segments can be registered at runtime via registry.set(), but that requires a deep import of dist/segments/registry.js, which Node and Deno reject under the package exports field (only . is exported). Baking the segments in makes them available without any deep import. (Companion PR #28 adds a ./dist/* subpath export for the cases that still need deep imports, e.g. subclassing CustomerOrderInteraction.)

Validation

docs/HKCCS.md documents the Sparkasse Berlin protocol specifics found during live validation: the ReqdExctnDt=1999-01-01 sentinel, the HKVPP-before-HKCCS ordering requirement, pushTAN method 923, and the success/failure response codes.

No dist/ committed. Build is clean; all 112 existing tests pass. The segments expose definitions only — no higher-level client API is added.

@tanacosa tanacosa force-pushed the feat/sepa-credit-transfer-segments branch from 564906b to 4047b05 Compare June 14, 2026 18:19
Registers HKCCS (Einreichung SEPA-Überweisung), its HKVPP pain.002
descriptor prefix, and HKIPZ (SEPA Instant / SCT Inst) as first-class
built-in segments, so consumers can issue SEPA wire transfers without
patching node_modules or reaching into dist/segments/registry.js at runtime.

The deep-import workaround crashes under Deno's npm: resolver because the
package's exports field does not expose the registry subpath, which blocks
every Deno-based consumer (edge functions, Deno Deploy, Cloudflare Workers
with Node compat). Registering the segments in
src/segments/registry.ts gives every consumer the writable payment surface
by default.

docs/HKCCS.md captures the Sparkasse Berlin protocol quirks observed during
live validation: the ReqdExctnDt=1999-01-01 sentinel, the HKVPP-before-HKCCS
ordering requirement, pushTAN method 923, and the response-code signatures.

All 112 existing tests pass; tsc build is clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tanacosa tanacosa force-pushed the feat/sepa-credit-transfer-segments branch from 4047b05 to 9dddda7 Compare June 14, 2026 18:21
@robocode13

robocode13 commented Jun 22, 2026

Copy link
Copy Markdown
Owner

Thanks for this, @tanacosa — and for validating against a live bank! 🙏 Adding transfer support is something I'm genuinely open to. But I'd like it built the same way as the rest of the library rather than merging segment definitions on their own.

The main concern: this is only part of a feature

Every capability in lib-fints is a triple:

  1. The segment definition(s), including the …S parameter segment (e.g. HISPAS for SEPA)
  2. An interaction orchestrator under interactions that handles the message flow and the TAN challenge
  3. A FinTSClient method guarded by a can…() capability check

This PR adds only (1). The usage example in docs/HKCCS.md then has consumers subclass CustomerOrderInteraction via a deep import to rebuild layer (2) themselves — which is exactly the deep-import path you note is broken on Deno. So on its own this PR doesn't give anyone a working transfer path; it pushes the hardest and riskiest parts outside the library, without the safety the rest of the codebase provides.

What I'd want before merging

  • pain message construction. The segment takes a raw sepaPainMessage, so all of the pain.001 XML — schema version, IBAN/BIC, amount formatting, ReqdExctnDt, end-to-end ID — has to be built by the consumer. The library already parses MT940/CAMT/MT535 on the read side; the write side needs the mirror image: a pain.001 builder (and ideally pain.002 status parsing) that takes structured transfer data, so the most error-prone part of a transfer isn't hand-rolled in user code.
  • Parameter segments + capability negotiation. HKCCS/HKIPZ have corresponding …S parameter segments in the BPD. Without parsing those we can't do real version negotiation or expose a canTransfer() / canInstantTransfer() check the way the library does everywhere else. (getMaxSupportedTransactionVersion is used in your example, but the parameters it depends on aren't parsed.)
  • An interaction + client API. A TransferInteraction plus FinTSClient.transfer(...) that runs the full dialog, returns a ClientResponse, and handles the TAN flow the same way statements do.
  • Response handling for the high-stakes codes. Partial execution (3040), instant-transfer async polling (3045HKIPS), fallback-to-SEPA (3270), etc. should surface through the normal bankAnswers / success mechanism, not be left to each consumer.
  • Tests. Convention here is a *.test.ts per segment in tests (encode/decode round-trips at minimum), plus coverage for the pain builder. The three new segments currently have none.
  • Bank-specific notes. The ReqdExctnDt=1999-01-01 sentinel, pushTAN method 923, and the HKVPP-before-HKCCS ordering are validated against Sparkasse Berlin. That's valuable, but I'd rather it not sit in docs as general protocol behaviour — please mark it clearly as observed-on-one-bank, or move it into code comments at the relevant spot.
  • README. Transfers are a deliberate write-capability boundary (the README currently says read-only). If we add them, that change should be explicit and intentional.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants