@atbas/m-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (366) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +364 -0
  3. package/dist/builder/transaction-builder.d.ts +53 -0
  4. package/dist/builder/transaction-builder.d.ts.map +1 -0
  5. package/dist/builder/transaction-builder.js +159 -0
  6. package/dist/builder/transaction-builder.js.map +1 -0
  7. package/dist/catalogue/default-catalogue.d.ts +18 -0
  8. package/dist/catalogue/default-catalogue.d.ts.map +1 -0
  9. package/dist/catalogue/default-catalogue.js +21 -0
  10. package/dist/catalogue/default-catalogue.js.map +1 -0
  11. package/dist/catalogue/endpoints.d.ts +22 -0
  12. package/dist/catalogue/endpoints.d.ts.map +1 -0
  13. package/dist/catalogue/endpoints.js +24 -0
  14. package/dist/catalogue/endpoints.js.map +1 -0
  15. package/dist/catalogue/flows.d.ts +32 -0
  16. package/dist/catalogue/flows.d.ts.map +1 -0
  17. package/dist/catalogue/flows.js +64 -0
  18. package/dist/catalogue/flows.js.map +1 -0
  19. package/dist/catalogue/hash-options.d.ts +112 -0
  20. package/dist/catalogue/hash-options.d.ts.map +1 -0
  21. package/dist/catalogue/hash-options.js +151 -0
  22. package/dist/catalogue/hash-options.js.map +1 -0
  23. package/dist/catalogue/types.d.ts +279 -0
  24. package/dist/catalogue/types.d.ts.map +1 -0
  25. package/dist/catalogue/types.js +360 -0
  26. package/dist/catalogue/types.js.map +1 -0
  27. package/dist/codegen/generate.d.ts +14 -0
  28. package/dist/codegen/generate.d.ts.map +1 -0
  29. package/dist/codegen/generate.js +490 -0
  30. package/dist/codegen/generate.js.map +1 -0
  31. package/dist/codegen/languages/node.d.ts +3 -0
  32. package/dist/codegen/languages/node.d.ts.map +1 -0
  33. package/dist/codegen/languages/node.js +32 -0
  34. package/dist/codegen/languages/node.js.map +1 -0
  35. package/dist/codegen/languages/php.d.ts +3 -0
  36. package/dist/codegen/languages/php.d.ts.map +1 -0
  37. package/dist/codegen/languages/php.js +27 -0
  38. package/dist/codegen/languages/php.js.map +1 -0
  39. package/dist/codegen/languages/python.d.ts +3 -0
  40. package/dist/codegen/languages/python.d.ts.map +1 -0
  41. package/dist/codegen/languages/python.js +27 -0
  42. package/dist/codegen/languages/python.js.map +1 -0
  43. package/dist/codegen/renderer.d.ts +24 -0
  44. package/dist/codegen/renderer.d.ts.map +1 -0
  45. package/dist/codegen/renderer.js +59 -0
  46. package/dist/codegen/renderer.js.map +1 -0
  47. package/dist/codegen/types.d.ts +50 -0
  48. package/dist/codegen/types.d.ts.map +1 -0
  49. package/dist/codegen/types.js +5 -0
  50. package/dist/codegen/types.js.map +1 -0
  51. package/dist/config/credentials.d.ts +64 -0
  52. package/dist/config/credentials.d.ts.map +1 -0
  53. package/dist/config/credentials.js +216 -0
  54. package/dist/config/credentials.js.map +1 -0
  55. package/dist/config/environment.d.ts +23 -0
  56. package/dist/config/environment.d.ts.map +1 -0
  57. package/dist/config/environment.js +54 -0
  58. package/dist/config/environment.js.map +1 -0
  59. package/dist/core/dependencies.d.ts +43 -0
  60. package/dist/core/dependencies.d.ts.map +1 -0
  61. package/dist/core/dependencies.js +2 -0
  62. package/dist/core/dependencies.js.map +1 -0
  63. package/dist/core/registry.d.ts +33 -0
  64. package/dist/core/registry.d.ts.map +1 -0
  65. package/dist/core/registry.js +13 -0
  66. package/dist/core/registry.js.map +1 -0
  67. package/dist/core/server.d.ts +61 -0
  68. package/dist/core/server.d.ts.map +1 -0
  69. package/dist/core/server.js +90 -0
  70. package/dist/core/server.js.map +1 -0
  71. package/dist/dependencies.d.ts +28 -0
  72. package/dist/dependencies.d.ts.map +1 -0
  73. package/dist/dependencies.js +2 -0
  74. package/dist/dependencies.js.map +1 -0
  75. package/dist/diagnostics/diagnose.d.ts +43 -0
  76. package/dist/diagnostics/diagnose.d.ts.map +1 -0
  77. package/dist/diagnostics/diagnose.js +121 -0
  78. package/dist/diagnostics/diagnose.js.map +1 -0
  79. package/dist/domain/amount.d.ts +157 -0
  80. package/dist/domain/amount.d.ts.map +1 -0
  81. package/dist/domain/amount.js +275 -0
  82. package/dist/domain/amount.js.map +1 -0
  83. package/dist/domain/datetime.d.ts +95 -0
  84. package/dist/domain/datetime.d.ts.map +1 -0
  85. package/dist/domain/datetime.js +211 -0
  86. package/dist/domain/datetime.js.map +1 -0
  87. package/dist/domain/response-codes.d.ts +116 -0
  88. package/dist/domain/response-codes.d.ts.map +1 -0
  89. package/dist/domain/response-codes.js +380 -0
  90. package/dist/domain/response-codes.js.map +1 -0
  91. package/dist/domain/secure-hash.d.ts +78 -0
  92. package/dist/domain/secure-hash.d.ts.map +1 -0
  93. package/dist/domain/secure-hash.js +69 -0
  94. package/dist/domain/secure-hash.js.map +1 -0
  95. package/dist/domain/signature/jazzcash.d.ts +56 -0
  96. package/dist/domain/signature/jazzcash.d.ts.map +1 -0
  97. package/dist/domain/signature/jazzcash.js +214 -0
  98. package/dist/domain/signature/jazzcash.js.map +1 -0
  99. package/dist/domain/signature/registry.d.ts +69 -0
  100. package/dist/domain/signature/registry.d.ts.map +1 -0
  101. package/dist/domain/signature/registry.js +92 -0
  102. package/dist/domain/signature/registry.js.map +1 -0
  103. package/dist/domain/signature/scheme.d.ts +349 -0
  104. package/dist/domain/signature/scheme.d.ts.map +1 -0
  105. package/dist/domain/signature/scheme.js +398 -0
  106. package/dist/domain/signature/scheme.js.map +1 -0
  107. package/dist/domain/txn-ref.d.ts +76 -0
  108. package/dist/domain/txn-ref.d.ts.map +1 -0
  109. package/dist/domain/txn-ref.js +126 -0
  110. package/dist/domain/txn-ref.js.map +1 -0
  111. package/dist/domain/types.d.ts +45 -0
  112. package/dist/domain/types.d.ts.map +1 -0
  113. package/dist/domain/types.js +70 -0
  114. package/dist/domain/types.js.map +1 -0
  115. package/dist/errors.d.ts +84 -0
  116. package/dist/errors.d.ts.map +1 -0
  117. package/dist/errors.js +87 -0
  118. package/dist/errors.js.map +1 -0
  119. package/dist/gateway/checkout-form.d.ts +16 -0
  120. package/dist/gateway/checkout-form.d.ts.map +1 -0
  121. package/dist/gateway/checkout-form.js +103 -0
  122. package/dist/gateway/checkout-form.js.map +1 -0
  123. package/dist/gateway/checkout-output.d.ts +70 -0
  124. package/dist/gateway/checkout-output.d.ts.map +1 -0
  125. package/dist/gateway/checkout-output.js +199 -0
  126. package/dist/gateway/checkout-output.js.map +1 -0
  127. package/dist/gateway/guards.d.ts +37 -0
  128. package/dist/gateway/guards.d.ts.map +1 -0
  129. package/dist/gateway/guards.js +44 -0
  130. package/dist/gateway/guards.js.map +1 -0
  131. package/dist/gateway/http-client.d.ts +42 -0
  132. package/dist/gateway/http-client.d.ts.map +1 -0
  133. package/dist/gateway/http-client.js +153 -0
  134. package/dist/gateway/http-client.js.map +1 -0
  135. package/dist/gateway/rest-client.d.ts +42 -0
  136. package/dist/gateway/rest-client.d.ts.map +1 -0
  137. package/dist/gateway/rest-client.js +241 -0
  138. package/dist/gateway/rest-client.js.map +1 -0
  139. package/dist/gateway/transport.d.ts +31 -0
  140. package/dist/gateway/transport.d.ts.map +1 -0
  141. package/dist/gateway/transport.js +73 -0
  142. package/dist/gateway/transport.js.map +1 -0
  143. package/dist/index.d.ts +3 -0
  144. package/dist/index.d.ts.map +1 -0
  145. package/dist/index.js +75 -0
  146. package/dist/index.js.map +1 -0
  147. package/dist/install/cli.d.ts +38 -0
  148. package/dist/install/cli.d.ts.map +1 -0
  149. package/dist/install/cli.js +274 -0
  150. package/dist/install/cli.js.map +1 -0
  151. package/dist/install/harnesses.d.ts +74 -0
  152. package/dist/install/harnesses.d.ts.map +1 -0
  153. package/dist/install/harnesses.js +263 -0
  154. package/dist/install/harnesses.js.map +1 -0
  155. package/dist/knowledge/corpus.d.ts +15 -0
  156. package/dist/knowledge/corpus.d.ts.map +1 -0
  157. package/dist/knowledge/corpus.js +129 -0
  158. package/dist/knowledge/corpus.js.map +1 -0
  159. package/dist/knowledge/search.d.ts +29 -0
  160. package/dist/knowledge/search.d.ts.map +1 -0
  161. package/dist/knowledge/search.js +181 -0
  162. package/dist/knowledge/search.js.map +1 -0
  163. package/dist/knowledge/source.d.ts +60 -0
  164. package/dist/knowledge/source.d.ts.map +1 -0
  165. package/dist/knowledge/source.js +91 -0
  166. package/dist/knowledge/source.js.map +1 -0
  167. package/dist/knowledge/types.d.ts +40 -0
  168. package/dist/knowledge/types.d.ts.map +1 -0
  169. package/dist/knowledge/types.js +19 -0
  170. package/dist/knowledge/types.js.map +1 -0
  171. package/dist/paths.d.ts +26 -0
  172. package/dist/paths.d.ts.map +1 -0
  173. package/dist/paths.js +106 -0
  174. package/dist/paths.js.map +1 -0
  175. package/dist/prompts/integration-walkthrough.d.ts +11 -0
  176. package/dist/prompts/integration-walkthrough.d.ts.map +1 -0
  177. package/dist/prompts/integration-walkthrough.js +52 -0
  178. package/dist/prompts/integration-walkthrough.js.map +1 -0
  179. package/dist/prompts/register.d.ts +4 -0
  180. package/dist/prompts/register.d.ts.map +1 -0
  181. package/dist/prompts/register.js +4 -0
  182. package/dist/prompts/register.js.map +1 -0
  183. package/dist/registry.d.ts +14 -0
  184. package/dist/registry.d.ts.map +1 -0
  185. package/dist/registry.js +2 -0
  186. package/dist/registry.js.map +1 -0
  187. package/dist/resources/knowledge-resources.d.ts +5 -0
  188. package/dist/resources/knowledge-resources.d.ts.map +1 -0
  189. package/dist/resources/knowledge-resources.js +121 -0
  190. package/dist/resources/knowledge-resources.js.map +1 -0
  191. package/dist/resources/register.d.ts +4 -0
  192. package/dist/resources/register.d.ts.map +1 -0
  193. package/dist/resources/register.js +8 -0
  194. package/dist/resources/register.js.map +1 -0
  195. package/dist/server.d.ts +40 -0
  196. package/dist/server.d.ts.map +1 -0
  197. package/dist/server.js +56 -0
  198. package/dist/server.js.map +1 -0
  199. package/dist/telemetry/logger.d.ts +31 -0
  200. package/dist/telemetry/logger.d.ts.map +1 -0
  201. package/dist/telemetry/logger.js +67 -0
  202. package/dist/telemetry/logger.js.map +1 -0
  203. package/dist/telemetry/redaction.d.ts +88 -0
  204. package/dist/telemetry/redaction.d.ts.map +1 -0
  205. package/dist/telemetry/redaction.js +238 -0
  206. package/dist/telemetry/redaction.js.map +1 -0
  207. package/dist/tools/build-transaction-parameters.d.ts +10 -0
  208. package/dist/tools/build-transaction-parameters.d.ts.map +1 -0
  209. package/dist/tools/build-transaction-parameters.js +154 -0
  210. package/dist/tools/build-transaction-parameters.js.map +1 -0
  211. package/dist/tools/call-context.d.ts +47 -0
  212. package/dist/tools/call-context.d.ts.map +1 -0
  213. package/dist/tools/call-context.js +15 -0
  214. package/dist/tools/call-context.js.map +1 -0
  215. package/dist/tools/codegen-tools.d.ts +4 -0
  216. package/dist/tools/codegen-tools.d.ts.map +1 -0
  217. package/dist/tools/codegen-tools.js +131 -0
  218. package/dist/tools/codegen-tools.js.map +1 -0
  219. package/dist/tools/credential-tools.d.ts +32 -0
  220. package/dist/tools/credential-tools.d.ts.map +1 -0
  221. package/dist/tools/credential-tools.js +65 -0
  222. package/dist/tools/credential-tools.js.map +1 -0
  223. package/dist/tools/descriptor.d.ts +52 -0
  224. package/dist/tools/descriptor.d.ts.map +1 -0
  225. package/dist/tools/descriptor.js +2 -0
  226. package/dist/tools/descriptor.js.map +1 -0
  227. package/dist/tools/diagnostic-tools.d.ts +3 -0
  228. package/dist/tools/diagnostic-tools.d.ts.map +1 -0
  229. package/dist/tools/diagnostic-tools.js +128 -0
  230. package/dist/tools/diagnostic-tools.js.map +1 -0
  231. package/dist/tools/gateway-tools.d.ts +6 -0
  232. package/dist/tools/gateway-tools.d.ts.map +1 -0
  233. package/dist/tools/gateway-tools.js +381 -0
  234. package/dist/tools/gateway-tools.js.map +1 -0
  235. package/dist/tools/hash-tools.d.ts +5 -0
  236. package/dist/tools/hash-tools.d.ts.map +1 -0
  237. package/dist/tools/hash-tools.js +238 -0
  238. package/dist/tools/hash-tools.js.map +1 -0
  239. package/dist/tools/knowledge-tools.d.ts +7 -0
  240. package/dist/tools/knowledge-tools.d.ts.map +1 -0
  241. package/dist/tools/knowledge-tools.js +247 -0
  242. package/dist/tools/knowledge-tools.js.map +1 -0
  243. package/dist/tools/onboarding-checklist.d.ts +3 -0
  244. package/dist/tools/onboarding-checklist.d.ts.map +1 -0
  245. package/dist/tools/onboarding-checklist.js +141 -0
  246. package/dist/tools/onboarding-checklist.js.map +1 -0
  247. package/dist/tools/register.d.ts +60 -0
  248. package/dist/tools/register.d.ts.map +1 -0
  249. package/dist/tools/register.js +145 -0
  250. package/dist/tools/register.js.map +1 -0
  251. package/dist/tools/tool-kit.d.ts +88 -0
  252. package/dist/tools/tool-kit.d.ts.map +1 -0
  253. package/dist/tools/tool-kit.js +297 -0
  254. package/dist/tools/tool-kit.js.map +1 -0
  255. package/dist/validation/payload-validator.d.ts +29 -0
  256. package/dist/validation/payload-validator.d.ts.map +1 -0
  257. package/dist/validation/payload-validator.js +79 -0
  258. package/dist/validation/payload-validator.js.map +1 -0
  259. package/dist/validation/rules/amount.d.ts +3 -0
  260. package/dist/validation/rules/amount.d.ts.map +1 -0
  261. package/dist/validation/rules/amount.js +77 -0
  262. package/dist/validation/rules/amount.js.map +1 -0
  263. package/dist/validation/rules/bill-reference.d.ts +10 -0
  264. package/dist/validation/rules/bill-reference.d.ts.map +1 -0
  265. package/dist/validation/rules/bill-reference.js +34 -0
  266. package/dist/validation/rules/bill-reference.js.map +1 -0
  267. package/dist/validation/rules/cnic.d.ts +3 -0
  268. package/dist/validation/rules/cnic.d.ts.map +1 -0
  269. package/dist/validation/rules/cnic.js +42 -0
  270. package/dist/validation/rules/cnic.js.map +1 -0
  271. package/dist/validation/rules/constants.d.ts +9 -0
  272. package/dist/validation/rules/constants.d.ts.map +1 -0
  273. package/dist/validation/rules/constants.js +28 -0
  274. package/dist/validation/rules/constants.js.map +1 -0
  275. package/dist/validation/rules/constraints.d.ts +3 -0
  276. package/dist/validation/rules/constraints.d.ts.map +1 -0
  277. package/dist/validation/rules/constraints.js +113 -0
  278. package/dist/validation/rules/constraints.js.map +1 -0
  279. package/dist/validation/rules/datetime.d.ts +3 -0
  280. package/dist/validation/rules/datetime.d.ts.map +1 -0
  281. package/dist/validation/rules/datetime.js +49 -0
  282. package/dist/validation/rules/datetime.js.map +1 -0
  283. package/dist/validation/rules/empty-string.d.ts +13 -0
  284. package/dist/validation/rules/empty-string.d.ts.map +1 -0
  285. package/dist/validation/rules/empty-string.js +32 -0
  286. package/dist/validation/rules/empty-string.js.map +1 -0
  287. package/dist/validation/rules/expiry.d.ts +3 -0
  288. package/dist/validation/rules/expiry.d.ts.map +1 -0
  289. package/dist/validation/rules/expiry.js +52 -0
  290. package/dist/validation/rules/expiry.js.map +1 -0
  291. package/dist/validation/rules/msisdn.d.ts +3 -0
  292. package/dist/validation/rules/msisdn.d.ts.map +1 -0
  293. package/dist/validation/rules/msisdn.js +45 -0
  294. package/dist/validation/rules/msisdn.js.map +1 -0
  295. package/dist/validation/rules/presence.d.ts +3 -0
  296. package/dist/validation/rules/presence.d.ts.map +1 -0
  297. package/dist/validation/rules/presence.js +90 -0
  298. package/dist/validation/rules/presence.js.map +1 -0
  299. package/dist/validation/rules/return-url.d.ts +14 -0
  300. package/dist/validation/rules/return-url.d.ts.map +1 -0
  301. package/dist/validation/rules/return-url.js +58 -0
  302. package/dist/validation/rules/return-url.js.map +1 -0
  303. package/dist/validation/rules/tool-argument.d.ts +16 -0
  304. package/dist/validation/rules/tool-argument.d.ts.map +1 -0
  305. package/dist/validation/rules/tool-argument.js +38 -0
  306. package/dist/validation/rules/tool-argument.js.map +1 -0
  307. package/dist/validation/rules/txn-ref.d.ts +3 -0
  308. package/dist/validation/rules/txn-ref.d.ts.map +1 -0
  309. package/dist/validation/rules/txn-ref.js +47 -0
  310. package/dist/validation/rules/txn-ref.js.map +1 -0
  311. package/dist/validation/rules/unknown-fields.d.ts +10 -0
  312. package/dist/validation/rules/unknown-fields.d.ts.map +1 -0
  313. package/dist/validation/rules/unknown-fields.js +29 -0
  314. package/dist/validation/rules/unknown-fields.js.map +1 -0
  315. package/dist/validation/types.d.ts +36 -0
  316. package/dist/validation/types.d.ts.map +1 -0
  317. package/dist/validation/types.js +12 -0
  318. package/dist/validation/types.js.map +1 -0
  319. package/dist/version.d.ts +23 -0
  320. package/dist/version.d.ts.map +1 -0
  321. package/dist/version.js +23 -0
  322. package/dist/version.js.map +1 -0
  323. package/knowledge/diagnostics/symptoms.json +321 -0
  324. package/knowledge/docs/bnpl-guide.md +77 -0
  325. package/knowledge/docs/card-page-redirection.md +67 -0
  326. package/knowledge/docs/card-refund.md +91 -0
  327. package/knowledge/docs/hmac-sha256-calculation.md +72 -0
  328. package/knowledge/docs/index.json +189 -0
  329. package/knowledge/docs/ipn-implementation.md +89 -0
  330. package/knowledge/docs/mwallet-recurring.md +117 -0
  331. package/knowledge/docs/mwallet-refund.md +65 -0
  332. package/knowledge/docs/mwallet-rest-v1-1.md +126 -0
  333. package/knowledge/docs/mwallet-rest-v2-0-cnic.md +113 -0
  334. package/knowledge/docs/portal-guide.md +45 -0
  335. package/knowledge/docs/shopify-guide.md +74 -0
  336. package/knowledge/docs/status-inquiry-2025-26.md +32 -0
  337. package/knowledge/docs/status-inquiry.md +111 -0
  338. package/knowledge/docs/wordpress-guide.md +49 -0
  339. package/knowledge/flow.schema.json +390 -0
  340. package/knowledge/flows/bnpl-page-redirection-v1.1.json +211 -0
  341. package/knowledge/flows/card-page-redirection-v1.1.json +211 -0
  342. package/knowledge/flows/mwallet-rest-v1.1.json +187 -0
  343. package/knowledge/flows/mwallet-rest-v2.0-cnic.json +197 -0
  344. package/knowledge/flows/mwallet-token-pay-v4.0.json +130 -0
  345. package/knowledge/flows/refund-bnpl.json +105 -0
  346. package/knowledge/flows/refund-card-v1.1.json +112 -0
  347. package/knowledge/flows/refund-card-v2.0.json +121 -0
  348. package/knowledge/flows/refund-mwallet-v1.1.json +106 -0
  349. package/knowledge/flows/status-inquiry-v1.1.json +102 -0
  350. package/knowledge/flows/status-inquiry-v2.0.json +103 -0
  351. package/knowledge/flows/token-delete-v1.json +85 -0
  352. package/knowledge/flows/token-inquiry-v1.json +85 -0
  353. package/knowledge/flows/wallet-linking-portal.json +103 -0
  354. package/knowledge/templates/node/checkout-redirect.tmpl +166 -0
  355. package/knowledge/templates/node/ipn-handler.tmpl +108 -0
  356. package/knowledge/templates/node/rest-client.tmpl +197 -0
  357. package/knowledge/templates/node/wallet-linking.tmpl +147 -0
  358. package/knowledge/templates/php/checkout-redirect.tmpl +149 -0
  359. package/knowledge/templates/php/ipn-handler.tmpl +105 -0
  360. package/knowledge/templates/php/rest-client.tmpl +191 -0
  361. package/knowledge/templates/php/wallet-linking.tmpl +137 -0
  362. package/knowledge/templates/python/checkout-redirect.tmpl +148 -0
  363. package/knowledge/templates/python/ipn-handler.tmpl +110 -0
  364. package/knowledge/templates/python/rest-client.tmpl +179 -0
  365. package/knowledge/templates/python/wallet-linking.tmpl +133 -0
  366. package/package.json +84 -0
@@ -0,0 +1,199 @@
1
+ import { chmodSync, closeSync, constants, existsSync, lstatSync, mkdirSync, openSync, realpathSync, writeSync, } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
4
+ import { JazzCashConfigError, JazzCashValidationError } from '../errors.js';
5
+ /**
6
+ * Where a signed checkout form may land, and how it is written there.
7
+ *
8
+ * Kept apart from the tools that call it. A generated form embeds the merchant's
9
+ * pp_Password as a hidden input and carries a valid pp_SecureHash, so deciding
10
+ * the destination and performing the write are the security-critical half of
11
+ * `jazzcash_build_checkout_form` — the half worth reading, unit-testing and
12
+ * gating on its own rather than reading past on the way to a tool registration.
13
+ *
14
+ * Nothing here may import `../paths.js`, `../dependencies.js` or
15
+ * `../registry.js`: this module sits inside the connector's published closure,
16
+ * and `scripts/closure.mjs` fails the build when the credential surface reaches
17
+ * the documentation half.
18
+ */
19
+ /**
20
+ * Server-side variable that relocates the checkout-form output directory.
21
+ *
22
+ * Deliberately not a tool argument. A generated form embeds the merchant's
23
+ * pp_Password as a hidden input and carries a valid pp_SecureHash, so where it
24
+ * lands is an operator decision: a caller — or a prompt injection reaching one —
25
+ * must not be able to steer it into a web root, a synced folder or a git tree.
26
+ */
27
+ const CHECKOUT_OUTPUT_DIRECTORY_VARIABLE = 'JAZZCASH_CHECKOUT_OUTPUT_DIR';
28
+ /**
29
+ * Variable naming the per-user state directory, per the XDG base directory spec.
30
+ *
31
+ * Not this server's variable: it belongs to the user's whole desktop session, so
32
+ * a value this module cannot use is ignored rather than treated as a fatal
33
+ * misconfiguration of the payment server.
34
+ */
35
+ const STATE_HOME_VARIABLE = 'XDG_STATE_HOME';
36
+ /** Mode every generated page is created and left with. */
37
+ const FORM_FILE_MODE = 0o600;
38
+ /** Mode the output directory is created with, when this call creates it. */
39
+ const FORM_DIRECTORY_MODE = 0o700;
40
+ /**
41
+ * Directory generated forms land in when the operator has named none.
42
+ *
43
+ * Deliberately NOT derived from the package root. This server is installed with
44
+ * `npx`, which unpacks it into a cache directory npm garbage-collects without
45
+ * warning: a default under the package would scatter pages embedding the
46
+ * merchant's password and a valid pp_SecureHash across `~/.npm/_npx/<hash>/`,
47
+ * where the operator neither expects them nor knows to delete them, and where a
48
+ * reinstall silently moves the directory out from under them.
49
+ *
50
+ * A per-user state directory is the right home instead. It is stable across
51
+ * reinstalls, it belongs to the operator rather than to a package manager, and
52
+ * `XDG_STATE_HOME` is the variable a user has already set if they keep such
53
+ * state somewhere other than `~/.local/state`.
54
+ *
55
+ * An empty, whitespace-only or relative `XDG_STATE_HOME` falls back rather than
56
+ * being used. A blank variable is an unset one, which is the same treatment
57
+ * {@link CHECKOUT_OUTPUT_DIRECTORY_VARIABLE} gets below. A relative one is
58
+ * ignored because the XDG specification says it must be, and because joining it
59
+ * would produce a relative path that {@link canonicalPath} anchors to
60
+ * `process.cwd()` — for a stdio server that is whatever the AI client chose,
61
+ * routinely the merchant's own project directory, which is exactly where a page
62
+ * carrying live credentials must never be written.
63
+ *
64
+ * Exported so the default can be asserted directly. Every suite that exercises
65
+ * the tool pins {@link CHECKOUT_OUTPUT_DIRECTORY_VARIABLE} to a temporary
66
+ * directory, so without this the default is the one path in this module no test
67
+ * would ever execute.
68
+ */
69
+ export function defaultCheckoutRoot() {
70
+ const stateHome = process.env[STATE_HOME_VARIABLE]?.trim() ?? '';
71
+ const usable = stateHome !== '' && isAbsolute(stateHome);
72
+ return join(usable ? stateHome : join(homedir(), '.local', 'state'), 'm-mcp', 'out');
73
+ }
74
+ /**
75
+ * Canonical absolute form of a path that need not exist yet.
76
+ *
77
+ * `realpathSync` throws on a missing path, so the deepest existing ancestor is
78
+ * resolved and the remaining segments are re-appended. Without this a symlink
79
+ * inside the output directory would defeat the containment check below. The
80
+ * walk terminates because `dirname` reaches a fixed point at the filesystem root.
81
+ *
82
+ * The final component is deliberately left unresolved when it does not exist,
83
+ * which is why {@link writeCheckoutForm} refuses to follow it rather than
84
+ * trusting this result: `existsSync` follows symlinks, so a *dangling* link at
85
+ * the target file name looks like a path that is simply absent.
86
+ */
87
+ function canonicalPath(target) {
88
+ const absolute = resolve(target);
89
+ const trailing = [];
90
+ let current = absolute;
91
+ for (;;) {
92
+ if (existsSync(current)) {
93
+ return join(realpathSync(current), ...trailing.reverse());
94
+ }
95
+ const parent = dirname(current);
96
+ /* c8 ignore next 3 -- unreachable while the filesystem root exists; retained because it is what proves this walk terminates */
97
+ if (parent === current) {
98
+ return absolute;
99
+ }
100
+ trailing.push(basename(current));
101
+ current = parent;
102
+ }
103
+ }
104
+ /** True when `candidate` sits underneath `root`. */
105
+ function isWithin(root, candidate) {
106
+ const offset = relative(root, candidate);
107
+ return offset !== '' && offset !== '..' && !offset.startsWith(`..${sep}`) && !isAbsolute(offset);
108
+ }
109
+ function assertWithinOutputRoot(root, candidate) {
110
+ if (isWithin(root, candidate)) {
111
+ return;
112
+ }
113
+ throw new JazzCashValidationError(`Refusing to write a signed checkout form to ${candidate}. The page embeds your merchant password and a valid pp_SecureHash, so it is only ever written inside ${root}. Pass outputPath as a file name relative to that directory, or set ${CHECKOUT_OUTPUT_DIRECTORY_VARIABLE} on the server to move the directory itself.`);
114
+ }
115
+ /**
116
+ * Refuse a target file name that is itself a symbolic link.
117
+ *
118
+ * The containment checks resolve every component *except* the last one, and they
119
+ * cannot do better: `existsSync` follows links, so a dangling link at the target
120
+ * name reports the path as absent and the walk hands back the literal in-root
121
+ * path. The write would then follow the link and deposit the merchant's password
122
+ * wherever it points, with both containment checks having returned true.
123
+ *
124
+ * This is the portable half of the refusal. `O_NOFOLLOW` below is the
125
+ * authoritative one — it also closes the window between this check and the open
126
+ * — but it does not exist on Windows, so the check is made here as well and the
127
+ * behaviour is the same on every platform.
128
+ */
129
+ function assertNotSymbolicLink(candidate) {
130
+ if (lstatSync(candidate, { throwIfNoEntry: false })?.isSymbolicLink() !== true) {
131
+ return;
132
+ }
133
+ throw new JazzCashValidationError(`Refusing to write a signed checkout form to ${candidate}, which is a symbolic link. The page embeds your merchant password and a valid pp_SecureHash, and a link is a redirection this server cannot vouch for: following it would put those credentials wherever the link points, outside the directory every containment check was made against. Delete the link, or pass outputPath as a different file name.`);
134
+ }
135
+ /**
136
+ * Decide where a checkout form may be written, refusing anything outside the
137
+ * server's own output directory.
138
+ *
139
+ * An escaping path is refused rather than silently rewritten: quietly relocating
140
+ * live credentials would hide where they actually landed.
141
+ */
142
+ export function resolveCheckoutTarget(outputPath, defaultFileName) {
143
+ const configured = process.env[CHECKOUT_OUTPUT_DIRECTORY_VARIABLE]?.trim() ?? '';
144
+ // Refused rather than resolved against `process.cwd()`, which is the same line
145
+ // `corpusRoot()` draws for `MCP_CORPUS_DIR` in `src/paths.ts`. A relative
146
+ // value here would not merely find the wrong directory: it would put a page
147
+ // carrying live credentials under whichever directory the AI client happened
148
+ // to start the server in, which is routinely a repository.
149
+ if (configured !== '' && !isAbsolute(configured)) {
150
+ throw new JazzCashConfigError(`${CHECKOUT_OUTPUT_DIRECTORY_VARIABLE} must be an absolute path, but is "${configured}". A relative path would be resolved against the working directory of whichever process started the server, which is not something this server can predict — and a generated form embeds your merchant password and a valid pp_SecureHash, so it must never land somewhere neither of us chose.`);
151
+ }
152
+ const root = canonicalPath(configured === '' ? defaultCheckoutRoot() : configured);
153
+ const requested = outputPath === undefined || outputPath.trim() === '' ? defaultFileName : outputPath.trim();
154
+ const path = canonicalPath(resolve(root, requested));
155
+ assertWithinOutputRoot(root, path);
156
+ return { root, path };
157
+ }
158
+ /**
159
+ * Write the page, re-checking containment once the directory exists.
160
+ *
161
+ * `resolveCheckoutTarget` could only resolve the symlinks present when it ran,
162
+ * and the write is what actually discloses the credentials, so the check is made
163
+ * again against the directory that now exists on disk.
164
+ *
165
+ * The directory is created 0700 because every file in it embeds the merchant's
166
+ * password and a valid pp_SecureHash. On a shared host the process umask alone
167
+ * would commonly leave it world-readable, and the mode is only applied to
168
+ * directories this call actually creates — an operator who pointed
169
+ * `JAZZCASH_CHECKOUT_OUTPUT_DIR` at an existing directory keeps their own
170
+ * permissions.
171
+ *
172
+ * The file is opened rather than handed to `writeFileSync` for two reasons that
173
+ * `writeFileSync` cannot serve at once. `O_NOFOLLOW` makes the open fail rather
174
+ * than follow a symbolic link at the target name, which is the one component no
175
+ * containment check could resolve, and it does so atomically — there is no
176
+ * window between the check and the write for a link to appear in. And `O_CREAT`
177
+ * carries the mode, so the page is 0600 from the moment it exists rather than
178
+ * whatever the umask allows. `chmodSync` follows because a mode passed to
179
+ * `open` is ignored for a file that already exists, and overwriting yesterday's
180
+ * world-readable page must tighten it rather than inherit it.
181
+ */
182
+ export function writeCheckoutForm(target, html) {
183
+ mkdirSync(dirname(target.path), { recursive: true, mode: FORM_DIRECTORY_MODE });
184
+ const confirmed = join(canonicalPath(dirname(target.path)), basename(target.path));
185
+ assertWithinOutputRoot(target.root, confirmed);
186
+ assertNotSymbolicLink(confirmed);
187
+ // `constants.O_NOFOLLOW` is absent on Windows, where the expression below
188
+ // degrades to the remaining flags. `assertNotSymbolicLink` is what keeps the
189
+ // refusal identical there.
190
+ const handle = openSync(confirmed, constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | constants.O_NOFOLLOW, FORM_FILE_MODE);
191
+ try {
192
+ writeSync(handle, html, 0, 'utf8');
193
+ }
194
+ finally {
195
+ closeSync(handle);
196
+ }
197
+ chmodSync(confirmed, FORM_FILE_MODE);
198
+ }
199
+ //# sourceMappingURL=checkout-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkout-output.js","sourceRoot":"","sources":["../../src/gateway/checkout-output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { IntegrationFlow } from '../catalogue/types.js';
2
+ import type { CredentialProfile } from '../config/credentials.js';
3
+ import type { JazzCashEnvironment } from '../config/environment.js';
4
+ import type { CoreDependencies } from '../core/dependencies.js';
5
+ /**
6
+ * Safety guards for outbound gateway calls.
7
+ *
8
+ * Every documented JazzCash flow uses an identical URL for sandbox and
9
+ * production. The endpoint therefore carries no information about which
10
+ * environment a request reaches: the credentials decide. Nothing here can be
11
+ * inferred, so everything is required explicitly.
12
+ *
13
+ * Production money movement needs BOTH:
14
+ * 1. the server started with `JAZZCASH_ALLOW_LIVE=true`, and
15
+ * 2. the tool call passing `confirmLiveEnvironment: true`.
16
+ *
17
+ * One switch could be left on by accident. Two, in different places and owned by
18
+ * different people, cannot be.
19
+ */
20
+ export interface GuardRequest {
21
+ readonly flow: IntegrationFlow;
22
+ readonly environment: JazzCashEnvironment;
23
+ readonly confirmLiveEnvironment: boolean | undefined;
24
+ }
25
+ export interface GuardOutcome {
26
+ readonly profile: CredentialProfile;
27
+ /** Warnings the caller must surface, e.g. that this call moves real money. */
28
+ readonly warnings: readonly string[];
29
+ }
30
+ /**
31
+ * Resolve credentials for a call and refuse it if the guards are not satisfied.
32
+ *
33
+ * Returns the warnings the caller must show, rather than logging them and moving
34
+ * on: a merchant about to move real money should see that on screen.
35
+ */
36
+ export declare function guardGatewayCall(deps: CoreDependencies, request: GuardRequest): GuardOutcome;
37
+ //# sourceMappingURL=guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../src/gateway/guards.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAC;IAC1C,QAAQ,CAAC,sBAAsB,EAAE,OAAO,GAAG,SAAS,CAAC;CACtD;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAkCD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,YAAY,GAAG,YAAY,CA6B5F"}
@@ -0,0 +1,44 @@
1
+ import { JazzCashSafetyError } from '../errors.js';
2
+ const SAFETY_DOC_REF = [{ docId: 'card-page-redirection', sectionId: 'endpoint' }];
3
+ function assertLiveOptIn(deps, request) {
4
+ if (request.environment !== 'production' || !request.flow.movesMoney) {
5
+ return;
6
+ }
7
+ if (!deps.config.allowLive) {
8
+ throw new JazzCashSafetyError(`Refusing to run ${request.flow.id} against production: this call moves real money and the server was started with JAZZCASH_ALLOW_LIVE=false. Restart with JAZZCASH_ALLOW_LIVE=true and pass confirmLiveEnvironment: true if that is genuinely what you intend. Note that the production endpoint is identical to the sandbox one, so this guard cannot be inferred away.`, { docRefs: SAFETY_DOC_REF, details: { flowId: request.flow.id } });
9
+ }
10
+ if (request.confirmLiveEnvironment !== true) {
11
+ throw new JazzCashSafetyError(`Refusing to run ${request.flow.id} against production without explicit confirmation. This call moves real money. Pass confirmLiveEnvironment: true to proceed.`, { docRefs: SAFETY_DOC_REF, details: { flowId: request.flow.id } });
12
+ }
13
+ }
14
+ function assertRefundCapability(flow, profile) {
15
+ const needsMpin = flow.parameters.some((parameter) => parameter.name === 'pp_MerchantMPIN');
16
+ if (needsMpin && !profile.supportsRefunds()) {
17
+ throw new JazzCashSafetyError(`${flow.id} requires pp_MerchantMPIN, but no MPIN is configured for the ${profile.environment} environment. Set JAZZCASH_${profile.environment.toUpperCase()}_MERCHANT_MPIN, and save the same MPIN in the merchant portal — refunds fail until it is stored there as well as sent.`, { docRefs: [{ docId: 'card-refund', sectionId: 'common-failures' }] });
18
+ }
19
+ }
20
+ /**
21
+ * Resolve credentials for a call and refuse it if the guards are not satisfied.
22
+ *
23
+ * Returns the warnings the caller must show, rather than logging them and moving
24
+ * on: a merchant about to move real money should see that on screen.
25
+ */
26
+ export function guardGatewayCall(deps, request) {
27
+ // Throws a JazzCashConfigError naming the missing variables when the profile
28
+ // is absent, which is a better failure than a 401 from the gateway.
29
+ const profile = deps.credentials.get(request.environment);
30
+ assertLiveOptIn(deps, request);
31
+ assertRefundCapability(request.flow, profile);
32
+ const warnings = [];
33
+ if (request.environment === 'production' && request.flow.movesMoney) {
34
+ warnings.push('This call is running against PRODUCTION and moves real money. It will debit or refund a real account.');
35
+ }
36
+ if (request.flow.sameEndpointForBothEnvironments) {
37
+ warnings.push(`The endpoint is identical for sandbox and production. This call is treated as ${request.environment} because that is the credential profile in use, not because of the URL.`);
38
+ }
39
+ if (request.flow.id === 'bnpl-page-redirection-v1.1' || request.flow.id === 'refund-bnpl') {
40
+ warnings.push('The BNPL guide specifies PRODUCTION credentials for testing. Use the smallest possible amount and refund it afterwards.');
41
+ }
42
+ return { profile, warnings };
43
+ }
44
+ //# sourceMappingURL=guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.js","sourceRoot":"","sources":["../../src/gateway/guards.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AA8BnD,MAAM,cAAc,GAAG,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;AAEnF,SAAS,eAAe,CAAC,IAAsB,EAAE,OAAqB;IACpE,IAAI,OAAO,CAAC,WAAW,KAAK,YAAY,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QACrE,OAAO;IACT,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QAC3B,MAAM,IAAI,mBAAmB,CAC3B,mBAAmB,OAAO,CAAC,IAAI,CAAC,EAAE,wUAAwU,EAC1W,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAClE,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,sBAAsB,KAAK,IAAI,EAAE,CAAC;QAC5C,MAAM,IAAI,mBAAmB,CAC3B,mBAAmB,OAAO,CAAC,IAAI,CAAC,EAAE,8HAA8H,EAChK,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAClE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAqB,EAAE,OAA0B;IAC/E,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,iBAAiB,CAAC,CAAC;IAC5F,IAAI,SAAS,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,mBAAmB,CAC3B,GAAG,IAAI,CAAC,EAAE,gEAAgE,OAAO,CAAC,WAAW,8BAA8B,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,wHAAwH,EACpR,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC,EAAE,CACtE,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAsB,EAAE,OAAqB;IAC5E,6EAA6E;IAC7E,oEAAoE;IACpE,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAE1D,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC/B,sBAAsB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE9C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,OAAO,CAAC,WAAW,KAAK,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QACpE,QAAQ,CAAC,IAAI,CACX,uGAAuG,CACxG,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,CAAC,+BAA+B,EAAE,CAAC;QACjD,QAAQ,CAAC,IAAI,CACX,iFAAiF,OAAO,CAAC,WAAW,yEAAyE,CAC9K,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,4BAA4B,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,aAAa,EAAE,CAAC;QAC1F,QAAQ,CAAC,IAAI,CACX,yHAAyH,CAC1H,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,42 @@
1
+ import type { Logger } from '../telemetry/logger.js';
2
+ /**
3
+ * HTTP transport for gateway calls.
4
+ *
5
+ * Deliberately small: native `fetch`, an explicit timeout, a bounded retry for
6
+ * reads only, and a response size cap. Request and response bodies are never
7
+ * logged — they carry the merchant password and, on some flows, a CNIC fragment.
8
+ */
9
+ /** Refuse to buffer more than this from a gateway response. */
10
+ export declare const MAX_RESPONSE_BYTES = 1048576;
11
+ export interface HttpClientOptions {
12
+ readonly timeoutMs: number;
13
+ readonly logger: Logger;
14
+ /** Injectable for tests. Defaults to the global `fetch`. */
15
+ readonly fetchImpl?: typeof fetch;
16
+ }
17
+ export interface HttpResponse {
18
+ readonly status: number;
19
+ readonly ok: boolean;
20
+ readonly rawText: string;
21
+ /** The parsed JSON body, or `undefined` when the body was not JSON. */
22
+ readonly body: unknown;
23
+ /** The declared media type, verbatim. Absent when the gateway declared none. */
24
+ readonly contentType?: string | undefined;
25
+ readonly durationMs: number;
26
+ readonly attempts: number;
27
+ }
28
+ export interface PostOptions {
29
+ /**
30
+ * Whether the call may be retried.
31
+ *
32
+ * Only ever true for reads. A payment or refund is NOT idempotent: retrying a
33
+ * request that may already have been processed can debit a customer twice.
34
+ * Resolve an uncertain outcome with the Status Inquiry API instead.
35
+ */
36
+ readonly retryable: boolean;
37
+ }
38
+ export interface HttpClient {
39
+ postJson(url: string, payload: unknown, options: PostOptions): Promise<HttpResponse>;
40
+ }
41
+ export declare function createHttpClient(options: HttpClientOptions): HttpClient;
42
+ //# sourceMappingURL=http-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../../src/gateway/http-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAErD;;;;;;GAMG;AAEH,+DAA+D;AAC/D,eAAO,MAAM,kBAAkB,UAAY,CAAC;AAE5C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CACnC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,gFAAgF;IAChF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CACtF;AAyFD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU,CA0FvE"}
@@ -0,0 +1,153 @@
1
+ import { JazzCashGatewayError } from '../errors.js';
2
+ /**
3
+ * HTTP transport for gateway calls.
4
+ *
5
+ * Deliberately small: native `fetch`, an explicit timeout, a bounded retry for
6
+ * reads only, and a response size cap. Request and response bodies are never
7
+ * logged — they carry the merchant password and, on some flows, a CNIC fragment.
8
+ */
9
+ /** Refuse to buffer more than this from a gateway response. */
10
+ export const MAX_RESPONSE_BYTES = 1_048_576;
11
+ /** One retry, and only for reads. The loop is bounded by construction. */
12
+ const MAX_ATTEMPTS_RETRYABLE = 2;
13
+ const RETRY_DELAY_MS = 500;
14
+ function isTransient(error) {
15
+ if (error instanceof DOMException && error.name === 'TimeoutError') {
16
+ return true;
17
+ }
18
+ return error instanceof TypeError;
19
+ }
20
+ function oversizedResponseError() {
21
+ return new JazzCashGatewayError(`The gateway returned more than ${String(MAX_RESPONSE_BYTES)} bytes, which no documented response approaches. Refusing to parse it.`);
22
+ }
23
+ /**
24
+ * Read a response body, refusing it as soon as it exceeds the cap.
25
+ *
26
+ * The body is consumed chunk by chunk and measured in BYTES. `response.text()`
27
+ * would defeat the cap twice over: it buffers the whole body before anything can
28
+ * be compared, so a fast endpoint could exhaust memory inside the timeout
29
+ * window, and its length is counted in UTF-16 code units, which under-counts
30
+ * every multi-byte character against a limit named in bytes.
31
+ */
32
+ async function readBoundedText(response) {
33
+ // A truthful Content-Length lets an oversized body be refused before a single
34
+ // chunk is read. An absent or unparseable header yields NaN and is ignored.
35
+ const declaredBytes = Number(response.headers.get('content-length'));
36
+ if (Number.isFinite(declaredBytes) && declaredBytes > MAX_RESPONSE_BYTES) {
37
+ throw oversizedResponseError();
38
+ }
39
+ // The runtime's fetch declarations type the body as a stream of `any`; the
40
+ // fetch specification always yields byte chunks, so it is named as such here
41
+ // rather than measuring an untyped value.
42
+ const body = response.body;
43
+ if (body === null) {
44
+ return '';
45
+ }
46
+ const reader = body.getReader();
47
+ const decoder = new TextDecoder();
48
+ let receivedBytes = 0;
49
+ let text = '';
50
+ try {
51
+ // Terminates on end of stream, or throws once the cap is exceeded. A body
52
+ // that never ends is bounded by the cap and by the request timeout.
53
+ let chunk = await reader.read();
54
+ while (!chunk.done) {
55
+ receivedBytes += chunk.value.byteLength;
56
+ if (receivedBytes > MAX_RESPONSE_BYTES) {
57
+ throw oversizedResponseError();
58
+ }
59
+ text += decoder.decode(chunk.value, { stream: true });
60
+ chunk = await reader.read();
61
+ }
62
+ }
63
+ catch (error) {
64
+ // Release the connection rather than leaving a half-read body open.
65
+ await reader.cancel().catch(() => undefined);
66
+ throw error;
67
+ }
68
+ return text + decoder.decode();
69
+ }
70
+ async function delay(milliseconds) {
71
+ await new Promise((resolve) => {
72
+ setTimeout(resolve, milliseconds);
73
+ });
74
+ }
75
+ export function createHttpClient(options) {
76
+ const fetchImpl = options.fetchImpl ?? fetch;
77
+ const attempt = async (url, plan) => {
78
+ const startedAt = Date.now();
79
+ const response = await fetchImpl(url, plan.buildInit());
80
+ const rawText = await readBoundedText(response);
81
+ const contentType = response.headers.get('content-type') ?? undefined;
82
+ return {
83
+ status: response.status,
84
+ ok: response.ok,
85
+ rawText,
86
+ body: plan.parseBody(rawText, contentType),
87
+ contentType,
88
+ durationMs: Date.now() - startedAt,
89
+ attempts: 1,
90
+ };
91
+ };
92
+ /**
93
+ * The retry loop, shared by every request shape.
94
+ *
95
+ * Written once so that a second transport cannot acquire a retry policy of its
96
+ * own: `retryable` is the only thing standing between a failed card sale and a
97
+ * second debit, and two copies of this loop are two places for it to drift.
98
+ */
99
+ const send = async (url, plan, postOptions) => {
100
+ const maxAttempts = postOptions.retryable ? MAX_ATTEMPTS_RETRYABLE : 1;
101
+ let lastError;
102
+ for (let attemptNumber = 1; attemptNumber <= maxAttempts; attemptNumber += 1) {
103
+ try {
104
+ const result = await attempt(url, plan);
105
+ return { ...result, attempts: attemptNumber };
106
+ }
107
+ catch (error) {
108
+ lastError = error;
109
+ const willRetry = attemptNumber < maxAttempts && isTransient(error);
110
+ options.logger.warn('Gateway request failed', {
111
+ url,
112
+ attempt: attemptNumber,
113
+ retryable: postOptions.retryable,
114
+ willRetry,
115
+ });
116
+ if (!willRetry) {
117
+ break;
118
+ }
119
+ await delay(RETRY_DELAY_MS);
120
+ }
121
+ }
122
+ const hint = postOptions.retryable
123
+ ? ''
124
+ : ' This call is not safe to retry automatically: it may already have been processed. Use the Status Inquiry API to establish the outcome before sending it again.';
125
+ throw new JazzCashGatewayError(`The JazzCash gateway could not be reached at ${url}.${hint}`, {
126
+ cause: lastError,
127
+ });
128
+ };
129
+ return {
130
+ async postJson(url, payload, postOptions) {
131
+ return send(url, {
132
+ buildInit: () => ({
133
+ method: 'POST',
134
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
135
+ body: JSON.stringify(payload),
136
+ signal: AbortSignal.timeout(options.timeoutMs),
137
+ }),
138
+ // Parsed whatever the gateway declares: a JSON body served as
139
+ // text/plain is common enough, and this is the shape every documented
140
+ // REST response takes.
141
+ parseBody: (rawText) => {
142
+ try {
143
+ return JSON.parse(rawText);
144
+ }
145
+ catch {
146
+ return undefined;
147
+ }
148
+ },
149
+ }, postOptions);
150
+ },
151
+ };
152
+ }
153
+ //# sourceMappingURL=http-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-client.js","sourceRoot":"","sources":["../../src/gateway/http-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import type { IntegrationFlow } from '../catalogue/types.js';
2
+ import type { JazzCashEnvironment } from '../config/environment.js';
3
+ import type { CoreDependencies } from '../core/dependencies.js';
4
+ import { type ClassifiedResponse } from '../domain/response-codes.js';
5
+ import { type RawParameters } from '../domain/types.js';
6
+ import { type HttpClient } from './http-client.js';
7
+ /**
8
+ * Execute a REST flow end to end: guard, fill credentials, validate, sign, send,
9
+ * verify, classify.
10
+ */
11
+ export type ResponseHashVerdict = 'verified' | 'unverified' | 'absent';
12
+ export interface ResponseHashCheck {
13
+ readonly verdict: ResponseHashVerdict;
14
+ /** Absent when the flow declares no response signature: there is no field. */
15
+ readonly field?: string | undefined;
16
+ readonly note: string;
17
+ }
18
+ export interface GatewayCallResult {
19
+ readonly flowId: string;
20
+ readonly environment: JazzCashEnvironment;
21
+ readonly endpoint: string;
22
+ /** The transmitted payload with credentials redacted. Safe to display. */
23
+ readonly requestPreview: Record<string, unknown>;
24
+ readonly response: Record<string, unknown>;
25
+ readonly httpStatus: number;
26
+ readonly durationMs: number;
27
+ readonly classification: ClassifiedResponse;
28
+ readonly responseHash: ResponseHashCheck;
29
+ readonly warnings: readonly string[];
30
+ readonly nextSteps: readonly string[];
31
+ }
32
+ export interface ExecuteOptions {
33
+ readonly flow: IntegrationFlow;
34
+ readonly environment: JazzCashEnvironment;
35
+ readonly parameters: RawParameters;
36
+ readonly confirmLiveEnvironment?: boolean | undefined;
37
+ /** Injectable so tests never touch the network. */
38
+ readonly httpClient?: HttpClient | undefined;
39
+ }
40
+ /** Send one REST request and interpret the result. */
41
+ export declare function executeFlow(deps: CoreDependencies, options: ExecuteOptions): Promise<GatewayCallResult>;
42
+ //# sourceMappingURL=rest-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rest-client.d.ts","sourceRoot":"","sources":["../../src/gateway/rest-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAExF,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAK5B,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGrE;;;GAGG;AAEH,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEvE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,kBAAkB,CAAC;IAC5C,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;IACnC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACtD,mDAAmD;IACnD,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAC9C;AAkOD,sDAAsD;AACtD,wBAAsB,WAAW,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAmE7G"}