@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,69 @@
1
+ import { createHmac } from 'node:crypto';
2
+ import { buildSignatureFor, computeSignatureFor, diagnoseSignatureFor, verifySignatureFor, } from './signature/registry.js';
3
+ import { JAZZCASH_SCHEME } from './signature/jazzcash.js';
4
+ import { signaturesMatch } from './signature/scheme.js';
5
+ /**
6
+ * The JazzCash forensic table.
7
+ *
8
+ * Reachable only as this scheme's property. Several entries describe how other
9
+ * gateways sign correctly, so a table shared between providers would report
10
+ * working code as a proven defect.
11
+ */
12
+ export const HASH_VARIANTS = JAZZCASH_SCHEME.variants;
13
+ /**
14
+ * Build the exact string that gets hashed, plus the reasoning behind it.
15
+ *
16
+ * Returning the breakdown rather than only the digest is the point: a merchant
17
+ * debugging `HASH_MISMATCH` needs to see which fields were used and in what
18
+ * order, which is precisely what no error message from the gateway tells them.
19
+ */
20
+ export function buildHashString(parameters, integritySalt, options) {
21
+ return buildSignatureFor(parameters, integritySalt, options);
22
+ }
23
+ /** HMAC-SHA256 a prepared string with the Integrity Salt as key. Lowercase hex. */
24
+ export function hmacSha256Hex(message, key) {
25
+ return createHmac('sha256', key).update(message, 'utf8').digest('hex');
26
+ }
27
+ /** Compute `pp_SecureHash` for a payload. Lowercase hex, as PHP's `hash_hmac` emits. */
28
+ export function computeSecureHash(parameters, integritySalt, options) {
29
+ return computeSignatureFor(parameters, integritySalt, options);
30
+ }
31
+ /**
32
+ * Constant-time, case-insensitive hash comparison.
33
+ *
34
+ * Case insensitivity is required, not merely tolerant: request samples in the
35
+ * guides are lowercase (PHP `hash_hmac` output) while response samples are
36
+ * uppercase. Both are the same digest.
37
+ */
38
+ export function hashesMatch(left, right) {
39
+ return signaturesMatch(left, right, 'case-insensitive');
40
+ }
41
+ /** Verify a supplied hash against a freshly computed one. */
42
+ export function verifySecureHash(parameters, integritySalt, providedHash, options) {
43
+ return verifySignatureFor(parameters, integritySalt, providedHash, options);
44
+ }
45
+ /**
46
+ * Explain why a hash does not match.
47
+ *
48
+ * Runs the selected scheme's known wrong constructions against the merchant's
49
+ * own parameters. A variant that reproduces their hash is reported as
50
+ * `confirmed`: that is not a guess, it is a demonstration of what their code
51
+ * did — which is why only the scheme the payload was signed under may be asked,
52
+ * and why `provenance` says whether the payload named that scheme.
53
+ *
54
+ * `provenance` is required rather than defaulted, for the same reason it is
55
+ * required on `diagnoseSignatureFor`: the safe value is the one that reports
56
+ * less, and a default of `declared` is the unsafe one, so a call site that
57
+ * forgot the argument would accuse a merchant of a construction error
58
+ * demonstrated under a construction nobody said they used. `declared` is the
59
+ * answer for every REQUEST — a flow's own hash specification selects the
60
+ * construction, and the flowless default selects `pp_`/`ppmpf_` fields only, so
61
+ * another provider's payload contributes nothing to it and no variant can
62
+ * reproduce that provider's signature. The response derivations are the ones
63
+ * that must pass `assumed`; see `requestHashOptions`, `responseHashOptions` and
64
+ * `forensicProvenance` in `src/catalogue/hash-options.ts`.
65
+ */
66
+ export function diagnoseHashMismatch(parameters, integritySalt, providedHash, options, provenance) {
67
+ return diagnoseSignatureFor(parameters, integritySalt, providedHash, options, provenance);
68
+ }
69
+ //# sourceMappingURL=secure-hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secure-hash.js","sourceRoot":"","sources":["../../src/domain/secure-hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,GAEnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAkC,MAAM,yBAAyB,CAAC;AAC1F,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAiCxD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAA2D,eAAe,CAAC,QAAQ,CAAC;AAE9G;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,UAAyB,EACzB,aAAqB,EACrB,OAA0B;IAE1B,OAAO,iBAAiB,CAAC,UAAU,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;AAC/D,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,aAAa,CAAC,OAAe,EAAE,GAAW;IACxD,OAAO,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzE,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,iBAAiB,CAC/B,UAAyB,EACzB,aAAqB,EACrB,OAA0B;IAE1B,OAAO,mBAAmB,CAAC,UAAU,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,KAAa;IACrD,OAAO,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,kBAAkB,CAAC,CAAC;AAC1D,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,gBAAgB,CAC9B,UAAyB,EACzB,aAAqB,EACrB,YAAoB,EACpB,OAA0B;IAE1B,OAAO,kBAAkB,CAAC,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,oBAAoB,CAClC,UAAyB,EACzB,aAAqB,EACrB,YAAoB,EACpB,OAAqC,EACrC,UAA4B;IAE5B,OAAO,oBAAoB,CAAC,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;AAC5F,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { type SignatureEncoding, type SignatureComparison, type SignatureScheme } from './scheme.js';
2
+ /**
3
+ * Per-flow configuration for the JazzCash scheme, as a caller may supply it.
4
+ *
5
+ * `scheme` is optional and single-valued so that every call site written before
6
+ * a second provider existed still selects this construction. Omitting it is not
7
+ * a default in the loose sense: an options object with no `scheme` cannot name
8
+ * any other one.
9
+ */
10
+ export interface JazzCashHashOptions {
11
+ readonly scheme?: 'jazzcash' | undefined;
12
+ /**
13
+ * Only fields starting with one of these prefixes participate.
14
+ *
15
+ * Assumption A1: the PHP samples include non-empty `ppmpf_*` fields, while the
16
+ * JavaScript linking sample selects only `pp_*`. The two disagree whenever a
17
+ * `ppmpf_*` field carries a value. The default follows the PHP samples;
18
+ * flow specifications may override it, so a correction from JazzCash is a data
19
+ * change rather than a code change.
20
+ */
21
+ readonly includeFieldPrefixes?: readonly string[] | undefined;
22
+ /** Fields excluded regardless of value. Defaults to the hash field itself. */
23
+ readonly excludeFields?: readonly string[] | undefined;
24
+ /**
25
+ * Treat a whitespace-only value as empty.
26
+ *
27
+ * Off by default: no guide says whitespace is stripped, and silently trimming
28
+ * would produce a hash the gateway does not expect. No flow declares it — the
29
+ * hash specification has no such field — so it is reachable only from a caller
30
+ * that passes these options directly, as a way of asking "would my hash match
31
+ * if my gateway ignored whitespace-only values?".
32
+ *
33
+ * It resolves into the plan, so the forensic table sees it too: every variant
34
+ * is the flow's OWN construction with one field changed, and a variant that
35
+ * quietly reverted this one would differ in two ways and would then name the
36
+ * wrong cause when it reproduced a merchant's hash. Reverting it is what the
37
+ * engine did before the plan existed.
38
+ */
39
+ readonly treatWhitespaceOnlyAsEmpty?: boolean | undefined;
40
+ /** Digest encoding. Defaults to the lowercase hex PHP's `hash_hmac` emits. */
41
+ readonly outputEncoding?: SignatureEncoding | undefined;
42
+ /** Comparison rule. Defaults to case-insensitive; see `SignatureComparison`. */
43
+ readonly comparison?: SignatureComparison | undefined;
44
+ }
45
+ /** The same configuration with every default already applied. */
46
+ export interface JazzCashSignatureSettings {
47
+ readonly includeFieldPrefixes: readonly string[];
48
+ readonly excludeFields: readonly string[];
49
+ readonly treatWhitespaceOnlyAsEmpty: boolean;
50
+ readonly outputEncoding?: SignatureEncoding | undefined;
51
+ readonly comparison?: SignatureComparison | undefined;
52
+ }
53
+ /** Apply the documented defaults to whatever the caller supplied. */
54
+ export declare function jazzCashSettings(options: JazzCashHashOptions | undefined): JazzCashSignatureSettings;
55
+ export declare const JAZZCASH_SCHEME: SignatureScheme<JazzCashSignatureSettings>;
56
+ //# sourceMappingURL=jazzcash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jazzcash.d.ts","sourceRoot":"","sources":["../../../src/domain/signature/jazzcash.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAIxB,KAAK,eAAe,EAErB,MAAM,aAAa,CAAC;AAgCrB;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACzC;;;;;;;;OAQG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAC9D,8EAA8E;IAC9E,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACvD;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1D,8EAA8E;IAC9E,QAAQ,CAAC,cAAc,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACxD,gFAAgF;IAChF,QAAQ,CAAC,UAAU,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;CACvD;AAED,iEAAiE;AACjE,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,oBAAoB,EAAE,SAAS,MAAM,EAAE,CAAC;IACjD,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,0BAA0B,EAAE,OAAO,CAAC;IAC7C,QAAQ,CAAC,cAAc,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACxD,QAAQ,CAAC,UAAU,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;CACvD;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,GAAG,SAAS,GAAG,yBAAyB,CAQpG;AAgLD,eAAO,MAAM,eAAe,EAAE,eAAe,CAAC,yBAAyB,CAatE,CAAC"}
@@ -0,0 +1,214 @@
1
+ import { defineVariants, describeConstruction, } from './scheme.js';
2
+ /**
3
+ * The JazzCash `pp_SecureHash` construction and its forensics.
4
+ *
5
+ * The algorithm, per `How is HMAC-SHA256 calculated (2026).pdf` and confirmed by
6
+ * the PHP and JavaScript samples in the redirection and linking guides:
7
+ *
8
+ * 1. Take every parameter whose value is non-empty.
9
+ * 2. Sort by parameter NAME, ascending ASCII.
10
+ * 3. Join the VALUES with `&`.
11
+ * 4. Prepend the Integrity Salt, separated by `&`.
12
+ * 5. HMAC-SHA256 the result, using the Integrity Salt as the secret key.
13
+ *
14
+ * Official worked example (salt `3vv9wu3a18`):
15
+ * `3vv9wu3a18&25000&MC25041&1234&sz1v4agvyf&PKR&T20220518150213`
16
+ *
17
+ * Two deliberate divergences from the official PHP sample, both bug fixes:
18
+ *
19
+ * - The sample uses loose comparison (`$value != ""`), which discards an
20
+ * integer `0`. This implementation treats a value as empty only when it is
21
+ * the empty string after normalisation.
22
+ * - The sample sorts with `ksort()` under `SORT_REGULAR`. This implementation
23
+ * sorts by ASCII code unit explicitly, which is what the specification says.
24
+ */
25
+ /** Prefixes whose fields participate in the hash by default. */
26
+ const DEFAULT_HASH_FIELD_PREFIXES = ['pp_', 'ppmpf_'];
27
+ /** Fields never included in their own hash input. */
28
+ const DEFAULT_EXCLUDED_HASH_FIELDS = ['pp_SecureHash', 'SecureHash'];
29
+ /** Apply the documented defaults to whatever the caller supplied. */
30
+ export function jazzCashSettings(options) {
31
+ return {
32
+ includeFieldPrefixes: options?.includeFieldPrefixes ?? DEFAULT_HASH_FIELD_PREFIXES,
33
+ excludeFields: options?.excludeFields ?? DEFAULT_EXCLUDED_HASH_FIELDS,
34
+ treatWhitespaceOnlyAsEmpty: options?.treatWhitespaceOnlyAsEmpty ?? false,
35
+ outputEncoding: options?.outputEncoding,
36
+ comparison: options?.comparison,
37
+ };
38
+ }
39
+ function jazzCashPlan(settings) {
40
+ return {
41
+ selection: {
42
+ kind: 'prefix',
43
+ includeFieldPrefixes: settings.includeFieldPrefixes,
44
+ excludeFields: settings.excludeFields,
45
+ },
46
+ ordering: 'name-ascending',
47
+ pairing: 'values-only',
48
+ valueTransform: 'as-transmitted',
49
+ omitEmptyValues: true,
50
+ treatWhitespaceOnlyAsEmpty: settings.treatWhitespaceOnlyAsEmpty,
51
+ separator: '&',
52
+ trailingSeparator: false,
53
+ secretPlacement: 'prepend',
54
+ primitive: 'hmac',
55
+ digest: 'sha256',
56
+ encoding: settings.outputEncoding ?? 'hex-lowercase',
57
+ comparison: settings.comparison ?? 'case-insensitive',
58
+ };
59
+ }
60
+ const JAZZCASH_SECRET = {
61
+ label: 'Integrity Salt',
62
+ role: 'It is both prepended to the hash string and used as the HMAC key, so it cannot produce a valid pp_SecureHash.',
63
+ docRefs: [{ docId: 'hmac-sha256-calculation', sectionId: 'how-is-hmac-sha256-calculated' }],
64
+ };
65
+ const JAZZCASH_NARRATIVE = {
66
+ matched: 'The hash matches. The secure hash was constructed correctly for this payload and salt.',
67
+ reproducedPrefix: 'Reproduced your hash exactly by applying a known construction error',
68
+ unexplained: 'The hash does not match and no known construction error reproduces it. The salt or the transmitted values are the most likely cause.',
69
+ };
70
+ /**
71
+ * The thirteen ways a JazzCash integration gets this wrong.
72
+ *
73
+ * Several entries — a plain digest, the salt at the far end, empty values kept —
74
+ * are how other gateways sign CORRECTLY, so what this table may be replayed
75
+ * against matters as much as what is in it.
76
+ *
77
+ * Two things keep that honest, and neither is the file boundary. Each entry is a
78
+ * single-field `PlanDelta` the engine applies to whatever plan it is bound to,
79
+ * so an entry cannot name a construction of its own; and `defineVariants` binds
80
+ * this table to `jazzCashPlan`, so every entry is the merchant's own JazzCash
81
+ * construction with exactly one field wrong. What the types do NOT enforce is
82
+ * that a delta table is bound to the scheme whose vocabulary it is written in —
83
+ * bound to another plan, these entries would describe real near misses of that
84
+ * plan in the wrong provider's words. `tests/domain/signature.test.ts` pins the
85
+ * binding per scheme, in both directions.
86
+ */
87
+ const JAZZCASH_VARIANT_DEFINITIONS = [
88
+ {
89
+ id: 'salt-appended',
90
+ label: 'Integrity Salt appended instead of prepended',
91
+ explanation: 'The salt is joined to the end of the value list rather than the beginning.',
92
+ fix: 'Build the string as `salt & value1 & value2 & …`. The salt comes first, before any parameter value.',
93
+ change: { set: 'secretPlacement', to: 'append' },
94
+ },
95
+ {
96
+ id: 'salt-omitted',
97
+ label: 'Integrity Salt not included in the hash string',
98
+ explanation: 'The salt is used as the HMAC key but never prepended to the message.',
99
+ fix: 'Prepend the salt to the concatenated values as well as using it as the HMAC key. It appears twice, by design.',
100
+ change: { set: 'secretPlacement', to: 'none' },
101
+ },
102
+ {
103
+ id: 'include-empty-fields',
104
+ label: 'Empty parameters included in the hash string',
105
+ explanation: 'Every declared parameter was concatenated, including those left as "". Empty fields must still be SENT, but must not be HASHED.',
106
+ fix: 'Skip parameters whose value is the empty string when building the hash string. Keep sending them in the request payload.',
107
+ change: { set: 'omitEmptyValues', to: false },
108
+ },
109
+ {
110
+ id: 'include-secure-hash-field',
111
+ label: 'pp_SecureHash included in its own input',
112
+ explanation: 'A previous hash value was left in the payload and fed back into the calculation.',
113
+ fix: 'Remove pp_SecureHash from the parameter set before computing the hash, then add it to the request afterwards.',
114
+ change: { set: 'excludeFields', to: [] },
115
+ },
116
+ {
117
+ id: 'pp-prefix-only',
118
+ label: 'ppmpf_* fields excluded from the hash',
119
+ explanation: 'Only fields named pp_* were hashed. The official JavaScript sample does this; the official PHP samples include non-empty ppmpf_* fields too.',
120
+ fix: 'Include non-empty ppmpf_1..5 in the hash string, or set the flow to pp_-only if JazzCash confirms that is correct for your account.',
121
+ change: { set: 'includeFieldPrefixes', to: ['pp_'] },
122
+ },
123
+ {
124
+ id: 'insertion-order',
125
+ label: 'Values concatenated in payload order rather than sorted',
126
+ explanation: 'The parameters were not sorted by name before their values were joined.',
127
+ fix: 'Sort the parameter NAMES ascending by ASCII, then join their VALUES in that order.',
128
+ change: { set: 'ordering', to: 'as-listed' },
129
+ },
130
+ {
131
+ id: 'descending-order',
132
+ label: 'Values sorted descending',
133
+ explanation: 'The sort direction is reversed.',
134
+ fix: 'Sort ascending, not descending.',
135
+ change: { set: 'ordering', to: 'name-descending' },
136
+ },
137
+ {
138
+ id: 'case-insensitive-sort',
139
+ label: 'Parameter names sorted case-insensitively',
140
+ explanation: 'Sorting was done after lower-casing the names, which reorders fields relative to ASCII order because uppercase letters sort before lowercase.',
141
+ fix: 'Sort the raw parameter names by ASCII code, without changing their case.',
142
+ change: { set: 'ordering', to: 'name-ascending-folded' },
143
+ },
144
+ {
145
+ id: 'key-value-pairs',
146
+ label: 'Keys concatenated alongside values',
147
+ explanation: 'The string was built as `name=value` pairs rather than values only.',
148
+ fix: 'Concatenate only the VALUES, separated by &. Parameter names are used for sorting, never for hashing.',
149
+ change: { set: 'pairing', to: 'name-and-value' },
150
+ },
151
+ {
152
+ id: 'no-separator',
153
+ label: 'Values concatenated without a separator',
154
+ explanation: 'The `&` between values was omitted.',
155
+ fix: 'Separate every value with a single & character, including between the salt and the first value.',
156
+ change: { set: 'separator', to: '' },
157
+ },
158
+ {
159
+ id: 'trailing-separator',
160
+ label: 'Trailing separator left on the end of the string',
161
+ explanation: 'The loop appended `value&` each iteration and the final `&` was never removed.',
162
+ fix: 'Strip the trailing & before hashing, or join the values instead of appending in a loop.',
163
+ change: { set: 'trailingSeparator', to: true },
164
+ },
165
+ {
166
+ id: 'plain-sha256',
167
+ label: 'Plain SHA-256 used instead of HMAC-SHA256',
168
+ explanation: 'The string was digested directly rather than keyed with the Integrity Salt.',
169
+ fix: 'Use HMAC-SHA256 with the Integrity Salt as the secret key, e.g. PHP `hash_hmac("sha256", $string, $salt)`.',
170
+ change: { set: 'primitive', to: 'digest' },
171
+ },
172
+ {
173
+ id: 'whitespace-trimmed',
174
+ label: 'Values trimmed before hashing',
175
+ explanation: 'A value carries leading or trailing whitespace in the request but was trimmed before hashing (or vice versa).',
176
+ fix: 'Hash exactly the value you transmit. Trim your inputs before you build the payload, not afterwards.',
177
+ change: { set: 'valueTransform', to: 'trimmed' },
178
+ },
179
+ ];
180
+ const JAZZCASH_ADVICE = [
181
+ {
182
+ id: 'wrong-salt',
183
+ label: 'The Integrity Salt does not match the account',
184
+ explanation: 'None of the common construction errors reproduce your hash, which most often means the salt itself is wrong — for example a sandbox salt used against production credentials, or a value copied with a stray character.',
185
+ fix: 'Re-copy the Integrity Salt from Integration > Credentials in the portal for the environment you are calling, and confirm it belongs to the same Merchant ID you are sending.',
186
+ },
187
+ {
188
+ id: 'value-differs-from-transmitted',
189
+ label: 'A hashed value differs from the transmitted value',
190
+ explanation: 'The hash was computed over a different payload than the one sent — commonly because the amount was converted, a timestamp was regenerated, or a field was modified after hashing.',
191
+ fix: 'Compute the hash as the last step, from the exact map you are about to transmit, and never mutate the payload afterwards.',
192
+ },
193
+ {
194
+ id: 'jazzcash-encoding-mismatch',
195
+ label: 'Character encoding differs',
196
+ explanation: 'A non-ASCII character in a description or bill reference was encoded differently when hashed and when sent.',
197
+ fix: 'Restrict pp_BillReference to alphanumerics as documented, and keep pp_Description ASCII where possible.',
198
+ },
199
+ ];
200
+ export const JAZZCASH_SCHEME = {
201
+ id: 'jazzcash',
202
+ label: 'JazzCash pp_SecureHash (HMAC-SHA256 over sorted values)',
203
+ secret: JAZZCASH_SECRET,
204
+ narrative: JAZZCASH_NARRATIVE,
205
+ plan: jazzCashPlan,
206
+ // Rendered from the resolved plan and this scheme's own name for its secret,
207
+ // so a flow that narrows the prefixes or declares base64 is described as it is
208
+ // configured. The hand-written sentence this replaces was the JazzCash one for
209
+ // every flow, including flows that do not sign this way at all.
210
+ describePlan: (plan) => describeConstruction(plan, JAZZCASH_SECRET.label),
211
+ variants: defineVariants(jazzCashPlan, JAZZCASH_VARIANT_DEFINITIONS),
212
+ advice: JAZZCASH_ADVICE,
213
+ };
214
+ //# sourceMappingURL=jazzcash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jazzcash.js","sourceRoot":"","sources":["../../../src/domain/signature/jazzcash.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import type { RawParameters } from '../types.js';
2
+ import { type JazzCashHashOptions } from './jazzcash.js';
3
+ import { type SchemeProvenance, type SignatureBreakdown, type SignatureDiagnosis, type SignatureScheme, type SignatureVerification } from './scheme.js';
4
+ /**
5
+ * Every signature scheme the server knows, and the one place a payload is
6
+ * matched to one.
7
+ *
8
+ * The options object carries the scheme with the settings it belongs to, so
9
+ * choosing a construction and configuring it are a single decision. The
10
+ * alternative — a scheme name in one argument and a settings bag in another —
11
+ * makes it possible to sign a payload with a construction nobody chose, or to
12
+ * diagnose it with another construction's forensic table, which is the failure
13
+ * mode this module exists to remove. One scheme is registered today; the
14
+ * indirection is what keeps that true if a second is ever added.
15
+ */
16
+ /** Configuration for one signature scheme, tagged with the scheme it selects. */
17
+ export type SignatureOptions = JazzCashHashOptions;
18
+ /** A construction described for a merchant to implement. */
19
+ export interface SignatureDescription {
20
+ /** How the string that is digested is built, and how it is digested. */
21
+ readonly construction: string;
22
+ /** The digest encoding and the comparison rule. */
23
+ readonly encoding: string;
24
+ }
25
+ /**
26
+ * Every registered scheme, and the table {@link withScheme} dispatches through.
27
+ *
28
+ * What keeps a scheme from being run with another scheme's settings is not this
29
+ * table: it is `SignatureOptions`, which carries the scheme name inside the
30
+ * settings object, so choosing a construction and configuring it are a single
31
+ * decision. Erasing the settings type to `never` here read as though the table
32
+ * enforced that, and a table credited with a guarantee it does not provide is
33
+ * one nobody dares give honest types to — which is how it ended up with no
34
+ * production consumer at all, describing a registry the signing path did not
35
+ * use.
36
+ *
37
+ * `satisfies` rather than an annotation for that reason: every member is pinned
38
+ * as a scheme, and each keeps the settings type it is actually executed with, so
39
+ * the branches below name a scheme and its own settings resolver together.
40
+ * `tests/domain/signature.test.ts` walks `SIGNATURE_SCHEME_IDS` through the
41
+ * table, so a scheme this file can reach but has not registered fails there.
42
+ */
43
+ export declare const SIGNATURE_SCHEMES: {
44
+ readonly jazzcash: SignatureScheme<import("./jazzcash.js").JazzCashSignatureSettings>;
45
+ };
46
+ /** Build the signed string and the reasoning behind it. */
47
+ export declare function buildSignatureFor(parameters: RawParameters, secret: string, options?: SignatureOptions): SignatureBreakdown;
48
+ /** Compute the signature for a payload. */
49
+ export declare function computeSignatureFor(parameters: RawParameters, secret: string, options?: SignatureOptions): string;
50
+ /** Verify a supplied signature against a freshly computed one. */
51
+ export declare function verifySignatureFor(parameters: RawParameters, secret: string, providedSignature: string, options?: SignatureOptions): SignatureVerification;
52
+ /**
53
+ * Explain a mismatch using the selected scheme's forensics, and no other's.
54
+ *
55
+ * `provenance` is required rather than defaulted, because the safe value is the
56
+ * one that reports less: a call site that forgot it would accuse a merchant of a
57
+ * construction error demonstrated under a construction nobody said they used.
58
+ */
59
+ export declare function diagnoseSignatureFor(parameters: RawParameters, secret: string, providedSignature: string, options: SignatureOptions | undefined, provenance: SchemeProvenance): SignatureDiagnosis;
60
+ /**
61
+ * How a payload signed under these options is built, in two sentences.
62
+ *
63
+ * Both are rendered from the RESOLVED plan rather than written at the call site.
64
+ * A paragraph written at the call site describes the construction its author had
65
+ * in mind rather than the one the engine ran, and a merchant implements the
66
+ * paragraph.
67
+ */
68
+ export declare function describeSignatureFor(options?: SignatureOptions): SignatureDescription;
69
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/domain/signature/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAqC,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC5F,OAAO,EAML,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EAEpB,KAAK,qBAAqB,EAC3B,MAAM,aAAa,CAAC;AAErB;;;;;;;;;;;GAWG;AAEH,iFAAiF;AACjF,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AAEnD,4DAA4D;AAC5D,MAAM,WAAW,oBAAoB;IACnC,wEAAwE;IACxE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,iBAAiB;;CAEkD,CAAC;AAsCjF,2DAA2D;AAC3D,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,aAAa,EACzB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,gBAAgB,GACzB,kBAAkB,CAIpB;AAED,2CAA2C;AAC3C,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAIjH;AAED,kEAAkE;AAClE,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,aAAa,EACzB,MAAM,EAAE,MAAM,EACd,iBAAiB,EAAE,MAAM,EACzB,OAAO,CAAC,EAAE,gBAAgB,GACzB,qBAAqB,CAIvB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,aAAa,EACzB,MAAM,EAAE,MAAM,EACd,iBAAiB,EAAE,MAAM,EACzB,OAAO,EAAE,gBAAgB,GAAG,SAAS,EACrC,UAAU,EAAE,gBAAgB,GAC3B,kBAAkB,CAIpB;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,oBAAoB,CAOrF"}
@@ -0,0 +1,92 @@
1
+ import { JAZZCASH_SCHEME, jazzCashSettings } from './jazzcash.js';
2
+ import { buildSignature, computeSignature, describeEncoding, diagnoseSignature, verifySignature, } from './scheme.js';
3
+ /**
4
+ * Every registered scheme, and the table {@link withScheme} dispatches through.
5
+ *
6
+ * What keeps a scheme from being run with another scheme's settings is not this
7
+ * table: it is `SignatureOptions`, which carries the scheme name inside the
8
+ * settings object, so choosing a construction and configuring it are a single
9
+ * decision. Erasing the settings type to `never` here read as though the table
10
+ * enforced that, and a table credited with a guarantee it does not provide is
11
+ * one nobody dares give honest types to — which is how it ended up with no
12
+ * production consumer at all, describing a registry the signing path did not
13
+ * use.
14
+ *
15
+ * `satisfies` rather than an annotation for that reason: every member is pinned
16
+ * as a scheme, and each keeps the settings type it is actually executed with, so
17
+ * the branches below name a scheme and its own settings resolver together.
18
+ * `tests/domain/signature.test.ts` walks `SIGNATURE_SCHEME_IDS` through the
19
+ * table, so a scheme this file can reach but has not registered fails there.
20
+ */
21
+ export const SIGNATURE_SCHEMES = {
22
+ jazzcash: JAZZCASH_SCHEME,
23
+ };
24
+ function withScheme(options, visitor) {
25
+ // Absent options mean JazzCash, the only construction the server ships. A
26
+ // second scheme must be named, never inferred from a missing field.
27
+ if (options === undefined) {
28
+ return visitor.run(SIGNATURE_SCHEMES.jazzcash, jazzCashSettings(undefined));
29
+ }
30
+ switch (options.scheme) {
31
+ case undefined:
32
+ case 'jazzcash':
33
+ return visitor.run(SIGNATURE_SCHEMES.jazzcash, jazzCashSettings(options));
34
+ }
35
+ // A scheme added to `SignatureOptions` and not to the switch fails on this
36
+ // line, naming itself. Without it the same omission surfaces as "lacks ending
37
+ // return statement" against the whole function, which invites a `default:`
38
+ // clause — and a default here means the new scheme's payloads are silently
39
+ // signed and diagnosed as JazzCash ones, which is exactly what this module
40
+ // exists to prevent.
41
+ /* c8 ignore start -- unreachable: the switch above is exhaustive, and the assignment below is what proves it */
42
+ const _exhaustive = options.scheme;
43
+ return _exhaustive;
44
+ /* c8 ignore stop */
45
+ }
46
+ /** Build the signed string and the reasoning behind it. */
47
+ export function buildSignatureFor(parameters, secret, options) {
48
+ return withScheme(options, {
49
+ run: (scheme, settings) => buildSignature(scheme, parameters, secret, settings),
50
+ });
51
+ }
52
+ /** Compute the signature for a payload. */
53
+ export function computeSignatureFor(parameters, secret, options) {
54
+ return withScheme(options, {
55
+ run: (scheme, settings) => computeSignature(scheme, parameters, secret, settings),
56
+ });
57
+ }
58
+ /** Verify a supplied signature against a freshly computed one. */
59
+ export function verifySignatureFor(parameters, secret, providedSignature, options) {
60
+ return withScheme(options, {
61
+ run: (scheme, settings) => verifySignature(scheme, parameters, secret, providedSignature, settings),
62
+ });
63
+ }
64
+ /**
65
+ * Explain a mismatch using the selected scheme's forensics, and no other's.
66
+ *
67
+ * `provenance` is required rather than defaulted, because the safe value is the
68
+ * one that reports less: a call site that forgot it would accuse a merchant of a
69
+ * construction error demonstrated under a construction nobody said they used.
70
+ */
71
+ export function diagnoseSignatureFor(parameters, secret, providedSignature, options, provenance) {
72
+ return withScheme(options, {
73
+ run: (scheme, settings) => diagnoseSignature(scheme, parameters, secret, providedSignature, settings, provenance),
74
+ });
75
+ }
76
+ /**
77
+ * How a payload signed under these options is built, in two sentences.
78
+ *
79
+ * Both are rendered from the RESOLVED plan rather than written at the call site.
80
+ * A paragraph written at the call site describes the construction its author had
81
+ * in mind rather than the one the engine ran, and a merchant implements the
82
+ * paragraph.
83
+ */
84
+ export function describeSignatureFor(options) {
85
+ return withScheme(options, {
86
+ run: (scheme, settings) => {
87
+ const plan = scheme.plan(settings);
88
+ return { construction: scheme.describePlan(plan), encoding: describeEncoding(plan) };
89
+ },
90
+ });
91
+ }
92
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/domain/signature/registry.ts"],"names":[],"mappings":"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"}