InstaCash external API + eSign headless test path (bin/instacash-cli) — 2026-06-01

Summary

How to drive the InstaCash external API (the integration the bank calls into vuer_oss) and the downstream eSign contract-upload plumbing headlessly from the vuer_oss container on the dev box, using the branch-only tool bin/instacash-cli.js. Section A is a reusable how-to (prereqs, every command, the SSH path, gotchas). Section B is the concrete 2026-06-01 verified run with its findings and one open question. Everything below was verified live on the lederera dev box on 2026-06-01.

Quick links: instacash-update-2026-05-27-status · devel-update-workflow · testing · dev-box-esign-container-startup-failures-2026-06-01 · dev-environment · esign

Hard limitation — the actual signature CANNOT be driven headless

instacash-cli proves the external API + EsignRPC plumbing end-to-end, but it cannot complete an eSign signature. The signature is interactive: a human opens the inviteUrl (css), does video identification, authenticates (mock /auth + SMS code), and signs in the eSign UI. See § Hard limitation.


Quick recipe

Drive the InstaCash external API headlessly (dev box)

# 0. SSH in (kaku shadows ssh → use `command ssh`; fk-dev = the current docker host)
command ssh ops@fk-dev.taild4189d.ts.net    # old `ssh Facekom` box is DEAD — see [[dev-build-host]]
 
# helper: every cli cmd runs INSIDE the vuer_oss container, in the app dir
ic() { docker exec vuer_oss sh -c "cd /workspace/vuer_oss && node bin/instacash-cli $*"; }
 
# 1. Start the MOCK bank /auth + /status server (DETACHED — it blocks)
docker exec -d vuer_oss sh -c \
  'cd /workspace/vuer_oss && node bin/instacash-cli start-server > /tmp/ic-mock.log 2>&1'
#   → /tmp/ic-mock.log: "InstaCash external server is listening on 8189"
 
# 2. Create an application (faker customer data) → returns customerId + URLs
ic post-application rt mkb_szemelyi_kolcson
#   → { customerId, customerProfileUrl, inviteUrl }
 
# 3. Inspect
ic get-invite <customerId>      # → { url: <videochat invite> }
ic get-customer <customerId>    # → full customer data (product, state, …)
 
# 4. Upload a contract (built-in dummy base64 PDF if no path) → ic-contract flow → EsignRPC
ic post-contract <customerId> [pdfPath]
ic get-contract <contractId>
ic revoke-contract <contractId>

Prereqs (all must hold): healthy stack (vuer_oss + esign_css + esign_oss + postgresql + rabbitmq + vuer_cv all Up/healthy); config.instacash.external present (apiKey = the Bearer token; authMock); settings.allowSelfSignedCerts: true. Every command except start-server boots the full vuer_oss service in-process and makes real HTTPS calls — it needs a live, conflict-free stack.


Section A — General how-to (reusable)

What the tool actually is

bin/instacash-cli.js (Node + commander; deps request-promise-native, express, faker) does two distinct jobs:

  1. Mocks the bank’s external endpointsstart-server stands up a small Express server exposing the bank-side /auth and /status endpoints that vuer_oss/eSign call out to during the flow.
  2. Drives the InstaCash external API — the rest of the subcommands act as the bank calling into vuer_oss, hitting https://${hosts.oss}/external/....

It is NOT just an HTTP client — every command (except start-server) boots the whole service

Each subcommand other than start-server boots the full vuer_oss service container in-process (keystore + Postgres + RabbitMQ amqps://localhost:5671), and only then makes the HTTPS call to https://${hosts.oss}/external/.... Consequences:

  • It requires a healthy, running stack and conflict-free config (e.g. nothing else holding the same ports / RabbitMQ already up).
  • Startup is not instant — expect the keystore/Postgres/RabbitMQ boot lines before the HTTP response.
  • A failure can come from the in-process boot, not just the remote endpoint — read the full output, not only the last line.

For Agents — orientation

  • Branch-only script. bin/instacash-cli.js exists only on customization/instacash (and its update/... branches); git show devel:bin/instacash-cli.js fails. It is not on devel. See customization-branches (per-customer bin: instacash → instacash-cli.js) and instacash-update-2026-05-27-status.
  • Where it runs: inside the vuer_oss container on the dev box. App dir /workspace/vuer_oss, branch customization/instacash, NODE_ENV=dev.
  • Auth: config.get('instacash.external.apiKey') is sent as the Bearer token to /external/....
  • TLS: the CLI sets NODE_TLS_REJECT_UNAUTHORIZED=0 for the dev self-signed certs; pair with settings.allowSelfSignedCerts: true in config.
  • State machine (from PortalData): none → initial → applied → identification → identified → signature → signed (+ aborted / rejected / accepted).

Prerequisites

All of these must be true or commands fail

  1. Healthy stackvuer_oss, esign_css, esign_oss, postgresql, rabbitmq, and vuer_cv all Up / healthy.
  2. Config instacash.external present:
    • instacash.external.apiKey → sent as the Bearer token on every /external/... call.
    • instacash.external.authMock → mock-auth settings the bank /auth endpoint uses.
  3. settings.allowSelfSignedCerts: true — the dev box uses self-signed certs; the CLI also sets NODE_TLS_REJECT_UNAUTHORIZED=0. Without this the HTTPS calls to https://${hosts.oss}/external/... fail TLS.

SSH to the dev box (from Claude’s shell)

Host changed (2026-07-01)

This session ran on the old ssh Facekom box (lederera@localhost via ProxyJump FKJumpBoxlederera-447-fk-hardver), now decommissioned. Current host: fk-devcommand ssh ops@fk-dev.taild4189d.ts.net (Tailscale SSH, no keypair, no jump box). The recipe is otherwise unchanged. See dev-build-host.

STILL TRUE — use command ssh (a kaku wrapper shadows plain ssh)

In Claude’s non-interactive shell the user’s kaku alias resolves to _kaku_wrapped_ssh: command not found, so plain ssh fails. Bypass with command ssh / command scp.

For non-interactive batches use a login shell so docker is on PATH:

command ssh ops@fk-dev.taild4189d.ts.net bash -l -s <<'EOF'
docker exec vuer_oss sh -c 'cd /workspace/vuer_oss && node bin/instacash-cli get-customer 28'
EOF

(Full SSH/host detail: dev-build-host. Old-box topology, for the record: 5. SSH access to the dev box from Claude Code’s shell.)

Commands

Invocation shape

Always docker exec vuer_oss sh -c 'cd /workspace/vuer_oss && node bin/instacash-cli <cmd>'. The cd matters — the script resolves config relative to the app dir.

start-server [port=8189] — mock bank /auth + /status

Stands up the mock bank-side endpoints. It blocks (long-running Express server), so run detached:

docker exec -d vuer_oss sh -c \
  'cd /workspace/vuer_oss && node bin/instacash-cli start-server > /tmp/ic-mock.log 2>&1'
# /tmp/ic-mock.log → "InstaCash external server is listening on 8189"

This is the only command that does not boot the full vuer_oss service in-process.

post-application [rt|nrt] [product] [externalCustomerId] [loan]

POST /external/application with faker-generated customer data. Creates the customer and returns the entry URLs.

  • rt / nrt — real-time vs non-real-time flow.
  • product ∈ mkb_szemelyi_kolcson | mkb_mszh | mbh_mfl.
  • optional externalCustomerId, loan.
  • Returns: { customerId, customerProfileUrl, inviteUrl }.

get-invite <customerId>

Returns the videochat invite URL → { url: <invite> } (same inviteUrl as post-application).

get-customer <customerId>

Full customer data (includes product, state, …).

post-contract <customerId> [pdfPath]

POST /external/contract (uses a built-in dummy base64 PDF if no pdfPath). This is the leg that exercises eSign:

post-contract → POST /external/contract
             → creates the "IC - Szerződés ajánlat feltöltése" (ic-contract) flow
             → EsignRPCClient
             → esign service (esign_oss / esign_css)

get-contract <contractId> / revoke-contract <contractId>

Read / revoke a previously-created contract.

Hard limitation — no headless signature

The actual eSign SIGNATURE is interactive and cannot be automated by this CLI

instacash-cli proves the external API + EsignRPC plumbing, but the signature itself requires a human in the loop:

  1. The customer opens the inviteUrl (css host).
  2. Completes video identification.
  3. Authenticates — mock /auth (from start-server) + the SMS code 123456 (config test.security.tempTokenSms; see sms-verification-code-dev-testing).
  4. Signs in the eSign UI.

There is no CLI subcommand that completes steps 1–4. Plan any “full flow” test to include a manual browser step at the inviteUrl.

Customer state machine (from PortalData)

stateDiagram-v2
    [*] --> none
    none --> initial
    initial --> applied
    applied --> identification
    identification --> identified
    identified --> signature
    signature --> signed
    signed --> [*]
    identification --> aborted
    signature --> aborted
    identification --> rejected
    signature --> accepted

For Agents

States: none → initial → applied → identification → identified → signature → signed, plus terminal/branch states aborted, rejected, accepted. instacash-cli can move a customer to created/applied (post-application) and exercise the contract API (post-contract), but identification → identified → signature → signed needs the interactive browser flow.


Section B — InstaCash-specific run (verified 2026-06-01)

Environment

lederera dev box, vuer_oss container, app dir /workspace/vuer_oss, branch customization/instacash, NODE_ENV=dev. Run during the InstaCash 2026-05-27 devel-update testing wave (after applying the nginx-PID fix to bring esign containers healthy).

The run, step by step

1. Mock server up

start-server  →  "InstaCash external server is listening on 8189"

2. Create application

post-application rt mkb_szemelyi_kolcson

→ booted vuer_oss in-process (keystore, Postgres, RabbitMQ amqps://localhost:5671), then:

FieldValue
customerId28
customerProfileUrlhttps://oss-lederera.facekomdev.net/customer/28
inviteUrlhttps://css-lederera.facekomdev.net/dch/eL90QmqJbqWXOjVd

3. Inspect

get-invite 28   → { url: https://css-lederera.facekomdev.net/dch/eL90QmqJbqWXOjVd }   # same invite
get-customer 28 → product: loan,  state: created

4. Upload contract — HTTP 400, blocked

post-contract 28

HTTP 400 with a clean JSON body:

{"error":"Contract flow is in progress"}

This is a clean rejection, not a crash

The 400 was served through nginx → vuer_oss as well-formed JSON. The plumbing (external API → nginx → vuer_oss → contract-flow logic) is working; the request was rejected by business logic, not a stack failure.

Open question to verify — flag for intended InstaCash behaviour

Why does a freshly-created application already have a contract flow "in progress"?

Customer 28 was just created via post-application and has not been identified (state: created). Yet post-contract is rejected with {"error":"Contract flow is in progress"} — implying a contract flow already exists/blocks the external upload at this stage.

This conflicts with developer-guide-hu.md, which states that contract upload happens AFTER identification. So either:

  • a contract flow is auto-created at application time (and the external upload is meant to wait until after identification), or
  • the guide and the current customization/instacash behaviour have drifted.

Action: verify the intended InstaCash sequencing — is post-contract expected to fail pre-identification, or should the external contract upload be allowed (and the “in progress” flow is the bug)? Reconcile against developer-guide-hu.md and the ic-contract (“IC - Szerződés ajánlat feltöltése”) flow creation point.

What this run proved (and didn’t)

ProvedNot proved (interactive only)
External API reachable: POST /external/application, get-invite, get-customer all return clean responses through nginx → vuer_ossVideo identification (identification → identified)
vuer_oss in-process boot (keystore, Postgres, RabbitMQ) works from the CLIAuthentication (mock /auth + SMS 123456)
Contract endpoint is wired and returns structured errors (the 400 was clean JSON, not a 5xx/crash)The actual eSign signature (signature → signed)
Mock bank server (/auth, /status) starts on 8189A successful post-contract (blocked by the “in progress” flow this run)

  • instacash-update-2026-05-27-status — the InstaCash 2026-05-27 devel-update wave this testing belongs to; per-repo branch/conflict topology (vuer_oss is on update/customization/instacash-2026-05-27).
  • dev-box-esign-container-startup-failures-2026-06-01prerequisite: the esign_css/esign_oss nginx-PID fix needed to make those containers healthy before the contract/eSign leg works.
  • dev-build-hostcurrent dev/build host (fk-dev Tailscale VM); the old ssh Facekom box is decommissioned.
  • dev-box-cv-photo-processing-failures — if identification’s photo step fails (vuer_cv stopped / hairpin NAT); the /etc/hosts remap that also keeps bin/instacash-cli’s oss-lederera/external/... path reachable after a docker restart.
  • sms-verification-code-dev-testing — the SMS code (123456, test.security.tempTokenSms) needed in the interactive auth step the CLI can’t drive.
  • esign — Electronic Signature System (esign_css / esign_oss) overview; what post-contract ultimately drives via EsignRPC.
  • esign-css-customization-branches — eSign standard dev/test method (test through VÜER CSS).
  • customization-branches — vuer_oss / vuer_css branch index; instacash-cli.js is the InstaCash per-customer bin script (branch-only).
  • devel-update-workflow — the devel → customization sync workflow this testing session belongs to.
  • testing — FaceKom testing reference.
  • dev-environment — FaceKom dev-environment reference (containers, supervisord, dev-box layout).
  • vuer_oss — backend service the external API and instacash-cli boot in-process.