Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Register
  • Sign in
  • A Ahad Mobile
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
  • Issues 0
    • Issues 0
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Terraform modules
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • holatech
  • Ahad Mobile
  • Merge requests
  • !80

feat(keysecure): sp1 client module for the keysecure card-issuing api

  • Review changes

  • Download
  • Patches
  • Plain diff
Merged Khanh Pham requested to merge feat/keysecure-sp1-foundation into develop Sep 25, 2026
  • Overview 0
  • Commits 21
  • Pipelines 1
  • Changes 42

Summary

Adds be/src/modules/keysecure/, a self-contained client for the KeySecure (ChainUp) card-issuing merchant API. This is SP1 of the card-issuing migration: the provider client only. No business flow, DB table, controller or FE change yet — nothing consumes the module so far.

  • Config — KEYSECURE_* env block. The module boots without credentials and throws KeySecureNotConfiguredError on first use, so environments without KeySecure are unaffected. Production requires an explicit KEYSECURE_BASE_URL.
  • Access token — shared through Redis (namespaced by base URL + Api-Key, cluster hash tag) with fenced single-flight refresh, so several API instances never revoke each other's token.
  • HTTP client — five request kinds with their own retry rules. Writes without an idempotency key (activate, status, PIN) and one-time client tokens are never replayed. A timeout, a 5xx, or a malformed success response on a write surfaces as outcomeUnknown, so callers reconcile by unique number instead of retrying blindly. Logging is whitelist-only: path templates with masked identifiers, no bodies, headers or tokens.
  • Crypto — AES-256-CBC with an IV prefix for PIN/CVV/private card data (key = SHA-256(apiSecret)), strict PIN rule (6 digits, no 3-digit identical/ascending/descending run), and callback HMAC-SHA256 verification. The canonical form is inferred; enforcement waits for a real sandbox callback (SP2).
  • Endpoints — 20 merchant endpoints (cardholder, card, account/reserve fund, consumption) with camelCase DTOs. Money stays a decimal string end to end (lossless-json).
  • Sandbox — 6 simulators (sandbox-only), plus yarn keysecure:smoke <token|packages|lists|reserve|crypto|bins|all|simulate>.

New dependency: lossless-json.

Test plan

  • yarn jest src/modules/keysecure — 171/171 pass
  • Full yarn test — only treasury.config.spec and admin-lending.risk.spec fail, identically at base 271a91f7 (pre-existing)
  • yarn build clean; eslint 0 errors on all changed files
  • yarn keysecure:smoke all against the real sandbox — token, packages, lists, reserve, crypto, bins (1012 = credit mode) all PASS
  • Full app boot (node dist/main) — KeySecureModule initialises, app starts
  • Per-task spec + quality review, whole-branch review, Codex review gate (approved in round 2)

Deploy note: with no KEYSECURE_* env set on staging the module stays dormant.

🤖 Generated with Claude Code

Assignee
Assign to
Reviewers
Request review from
Time tracking
Source branch: feat/keysecure-sp1-foundation