@kya-os/mcp-i 0.1.0-alpha.3.9 → 1.2.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 (328) hide show
  1. package/README.md +350 -213
  2. package/dist/149.js +1 -0
  3. package/dist/189.js +1 -0
  4. package/dist/261.js +1 -0
  5. package/dist/28.js +1 -0
  6. package/dist/295.js +1 -0
  7. package/dist/460.js +1 -0
  8. package/dist/570.js +1 -0
  9. package/dist/634.js +1 -0
  10. package/dist/647.js +1 -0
  11. package/dist/67.js +1 -0
  12. package/dist/739.js +1 -0
  13. package/dist/742.js +1 -0
  14. package/dist/904.js +1 -0
  15. package/dist/938.js +1 -0
  16. package/dist/auth/api-key.d.ts +16 -0
  17. package/dist/auth/api-key.js +82 -0
  18. package/dist/auth/jwt.d.ts +43 -0
  19. package/dist/auth/jwt.js +51 -0
  20. package/dist/auth/oauth/factory.d.ts +12 -0
  21. package/dist/auth/oauth/factory.js +36 -0
  22. package/dist/auth/oauth/index.d.ts +5 -0
  23. package/dist/auth/oauth/index.js +27 -0
  24. package/dist/auth/oauth/providers/proxy-provider.d.ts +13 -0
  25. package/dist/auth/oauth/providers/proxy-provider.js +159 -0
  26. package/dist/auth/oauth/router.d.ts +4 -0
  27. package/dist/auth/oauth/router.js +294 -0
  28. package/dist/auth/oauth/storage/memory-storage.d.ts +12 -0
  29. package/dist/auth/oauth/storage/memory-storage.js +40 -0
  30. package/dist/auth/oauth/types.d.ts +112 -0
  31. package/dist/cache/__tests__/cloudflare-kv-nonce-cache.test.d.ts +4 -0
  32. package/dist/cache/__tests__/cloudflare-kv-nonce-cache.test.js +176 -0
  33. package/dist/cache/__tests__/concurrency.test.d.ts +5 -0
  34. package/dist/cache/__tests__/concurrency.test.js +300 -0
  35. package/dist/cache/__tests__/dynamodb-nonce-cache.test.d.ts +4 -0
  36. package/dist/cache/__tests__/dynamodb-nonce-cache.test.js +176 -0
  37. package/dist/cache/__tests__/memory-nonce-cache.test.d.ts +4 -0
  38. package/dist/cache/__tests__/memory-nonce-cache.test.js +132 -0
  39. package/dist/cache/__tests__/nonce-cache-factory-simple.test.d.ts +4 -0
  40. package/dist/cache/__tests__/nonce-cache-factory-simple.test.js +133 -0
  41. package/dist/cache/__tests__/nonce-cache-factory.test.d.ts +4 -0
  42. package/dist/cache/__tests__/nonce-cache-factory.test.js +252 -0
  43. package/dist/cache/__tests__/redis-nonce-cache.test.d.ts +4 -0
  44. package/dist/cache/__tests__/redis-nonce-cache.test.js +95 -0
  45. package/dist/cache/cloudflare-kv-nonce-cache.d.ts +14 -0
  46. package/dist/cache/cloudflare-kv-nonce-cache.js +93 -0
  47. package/dist/cache/dynamodb-nonce-cache.d.ts +15 -0
  48. package/dist/cache/dynamodb-nonce-cache.js +92 -0
  49. package/dist/cache/index.d.ts +16 -0
  50. package/dist/cache/index.js +32 -0
  51. package/dist/cache/memory-nonce-cache.d.ts +44 -0
  52. package/dist/cache/memory-nonce-cache.js +105 -0
  53. package/dist/cache/nonce-cache-factory.d.ts +20 -0
  54. package/dist/cache/nonce-cache-factory.js +208 -0
  55. package/dist/cache/redis-nonce-cache.d.ts +14 -0
  56. package/dist/cache/redis-nonce-cache.js +53 -0
  57. package/dist/compiler/compiler-context.d.ts +23 -0
  58. package/dist/compiler/compiler-context.js +24 -0
  59. package/dist/compiler/config/constants.d.ts +41 -0
  60. package/dist/compiler/config/constants.js +45 -0
  61. package/dist/compiler/config/index.d.ts +252 -0
  62. package/dist/compiler/config/index.js +15 -0
  63. package/dist/compiler/config/injection.d.ts +26 -0
  64. package/dist/compiler/config/injection.js +58 -0
  65. package/dist/compiler/config/schemas/experimental/index.d.ts +91 -0
  66. package/dist/compiler/config/schemas/experimental/index.js +16 -0
  67. package/dist/compiler/config/schemas/experimental/oauth.d.ts +74 -0
  68. package/dist/compiler/config/schemas/experimental/oauth.js +25 -0
  69. package/dist/compiler/config/schemas/index.d.ts +6 -0
  70. package/dist/compiler/config/schemas/index.js +17 -0
  71. package/dist/compiler/config/schemas/paths.d.ts +9 -0
  72. package/dist/compiler/config/schemas/paths.js +12 -0
  73. package/dist/compiler/config/schemas/transport/http.d.ts +82 -0
  74. package/dist/compiler/config/schemas/transport/http.js +33 -0
  75. package/dist/compiler/config/schemas/transport/stdio.d.ts +9 -0
  76. package/dist/compiler/config/schemas/transport/stdio.js +15 -0
  77. package/dist/compiler/config/schemas/webpack.d.ts +3 -0
  78. package/dist/compiler/config/schemas/webpack.js +15 -0
  79. package/dist/compiler/config/types.d.ts +1 -0
  80. package/dist/compiler/config/types.js +2 -0
  81. package/dist/compiler/config/utils.d.ts +20 -0
  82. package/dist/compiler/config/utils.js +36 -0
  83. package/dist/compiler/generate-env-code.d.ts +1 -0
  84. package/dist/compiler/generate-env-code.js +8 -0
  85. package/dist/compiler/generate-import-code.d.ts +1 -0
  86. package/dist/compiler/generate-import-code.js +24 -0
  87. package/dist/compiler/get-webpack-config/get-entries.d.ts +3 -0
  88. package/dist/compiler/get-webpack-config/get-entries.js +29 -0
  89. package/dist/compiler/get-webpack-config/get-externals.d.ts +7 -0
  90. package/dist/compiler/get-webpack-config/get-externals.js +88 -0
  91. package/dist/compiler/get-webpack-config/get-injected-variables.d.ts +8 -0
  92. package/dist/compiler/get-webpack-config/get-injected-variables.js +25 -0
  93. package/dist/compiler/get-webpack-config/index.d.ts +4 -0
  94. package/dist/compiler/get-webpack-config/index.js +101 -0
  95. package/dist/compiler/get-webpack-config/plugins.d.ts +8 -0
  96. package/dist/compiler/get-webpack-config/plugins.js +132 -0
  97. package/dist/compiler/get-webpack-config/resolve-tsconfig-paths.d.ts +9 -0
  98. package/dist/compiler/get-webpack-config/resolve-tsconfig-paths.js +40 -0
  99. package/dist/compiler/index.d.ts +6 -0
  100. package/dist/compiler/index.js +194 -0
  101. package/dist/compiler/on-first-build.d.ts +3 -0
  102. package/dist/compiler/on-first-build.js +58 -0
  103. package/dist/compiler/parse-xmcp-config.d.ts +9 -0
  104. package/dist/compiler/parse-xmcp-config.js +155 -0
  105. package/dist/compiler/start-http-server.d.ts +1 -0
  106. package/dist/compiler/start-http-server.js +34 -0
  107. package/dist/index.d.ts +12 -0
  108. package/dist/index.js +38 -0
  109. package/dist/index.js.LICENSE.txt +49 -0
  110. package/dist/runtime/__tests__/audit.test.d.ts +4 -0
  111. package/dist/runtime/__tests__/audit.test.js +328 -0
  112. package/dist/runtime/__tests__/identity.test.d.ts +4 -0
  113. package/dist/runtime/__tests__/identity.test.js +164 -0
  114. package/dist/runtime/__tests__/mcpi-runtime.test.d.ts +4 -0
  115. package/dist/runtime/__tests__/mcpi-runtime.test.js +372 -0
  116. package/dist/runtime/__tests__/proof.test.d.ts +4 -0
  117. package/dist/runtime/__tests__/proof.test.js +302 -0
  118. package/dist/runtime/__tests__/session.test.d.ts +4 -0
  119. package/dist/runtime/__tests__/session.test.js +254 -0
  120. package/dist/runtime/__tests__/well-known.test.d.ts +4 -0
  121. package/dist/runtime/__tests__/well-known.test.js +312 -0
  122. package/dist/runtime/adapter-express.js +2 -0
  123. package/dist/runtime/adapter-express.js.LICENSE.txt +252 -0
  124. package/dist/runtime/adapter-nextjs.js +2 -0
  125. package/dist/runtime/adapter-nextjs.js.LICENSE.txt +53 -0
  126. package/dist/runtime/adapters/express/index.d.ts +2 -0
  127. package/dist/runtime/adapters/express/index.js +48 -0
  128. package/dist/runtime/adapters/nextjs/index.d.ts +8 -0
  129. package/dist/runtime/adapters/nextjs/index.js +18 -0
  130. package/dist/runtime/audit.d.ts +93 -0
  131. package/dist/runtime/audit.js +212 -0
  132. package/dist/runtime/debug.d.ts +118 -0
  133. package/dist/runtime/debug.js +612 -0
  134. package/dist/runtime/delegation-hooks.d.ts +85 -0
  135. package/dist/runtime/delegation-hooks.js +116 -0
  136. package/dist/runtime/demo.d.ts +71 -0
  137. package/dist/runtime/demo.js +135 -0
  138. package/dist/runtime/headers.d.ts +1 -0
  139. package/dist/runtime/headers.js +9 -0
  140. package/dist/runtime/http.js +2 -0
  141. package/dist/runtime/http.js.LICENSE.txt +252 -0
  142. package/dist/runtime/identity.d.ts +105 -0
  143. package/dist/runtime/identity.js +232 -0
  144. package/dist/runtime/index.d.ts +16 -0
  145. package/dist/runtime/index.js +56 -0
  146. package/dist/runtime/mcpi-runtime.d.ts +164 -0
  147. package/dist/runtime/mcpi-runtime.js +352 -0
  148. package/dist/runtime/proof.d.ts +87 -0
  149. package/dist/runtime/proof.js +223 -0
  150. package/dist/runtime/session.d.ts +88 -0
  151. package/dist/runtime/session.js +216 -0
  152. package/dist/runtime/stdio.js +2 -0
  153. package/dist/runtime/stdio.js.LICENSE.txt +1 -0
  154. package/dist/runtime/templates/home.d.ts +2 -0
  155. package/dist/runtime/templates/home.js +50 -0
  156. package/dist/runtime/transports/http/base-streamable-http.d.ts +25 -0
  157. package/dist/runtime/transports/http/base-streamable-http.js +16 -0
  158. package/dist/runtime/transports/http/http-context.d.ts +9 -0
  159. package/dist/runtime/transports/http/http-context.js +8 -0
  160. package/dist/runtime/transports/http/index.js +55 -0
  161. package/dist/runtime/transports/http/setup-cors.d.ts +4 -0
  162. package/dist/runtime/transports/http/setup-cors.js +24 -0
  163. package/dist/runtime/transports/http/stateless-streamable-http.d.ts +39 -0
  164. package/dist/runtime/transports/http/stateless-streamable-http.js +331 -0
  165. package/dist/runtime/transports/stdio/index.d.ts +1 -0
  166. package/dist/runtime/transports/stdio/index.js +51 -0
  167. package/dist/runtime/utils/server.d.ts +42 -0
  168. package/dist/runtime/utils/server.js +39 -0
  169. package/dist/runtime/utils/tools.d.ts +8 -0
  170. package/dist/runtime/utils/tools.js +115 -0
  171. package/dist/runtime/verifier-middleware.d.ts +76 -0
  172. package/dist/runtime/verifier-middleware.js +322 -0
  173. package/dist/runtime/well-known.d.ts +151 -0
  174. package/dist/runtime/well-known.js +258 -0
  175. package/dist/storage/config.d.ts +28 -0
  176. package/dist/storage/config.js +79 -0
  177. package/dist/storage/delegation.d.ts +59 -0
  178. package/dist/storage/delegation.js +130 -0
  179. package/dist/storage/merkle-verifier.d.ts +84 -0
  180. package/dist/storage/merkle-verifier.js +261 -0
  181. package/dist/test/__tests__/nonce-cache-integration.test.d.ts +1 -0
  182. package/dist/test/__tests__/nonce-cache-integration.test.js +116 -0
  183. package/dist/test/__tests__/nonce-cache.test.d.ts +1 -0
  184. package/dist/test/__tests__/nonce-cache.test.js +122 -0
  185. package/dist/test/__tests__/runtime-integration.test.d.ts +4 -0
  186. package/dist/test/__tests__/runtime-integration.test.js +192 -0
  187. package/dist/test/__tests__/test-infrastructure.test.d.ts +4 -0
  188. package/dist/test/__tests__/test-infrastructure.test.js +178 -0
  189. package/dist/test/deterministic-keys.d.ts +31 -0
  190. package/dist/test/deterministic-keys.js +108 -0
  191. package/dist/test/examples/test-usage-example.d.ts +140 -0
  192. package/dist/test/examples/test-usage-example.js +175 -0
  193. package/dist/test/index.d.ts +11 -0
  194. package/dist/test/index.js +27 -0
  195. package/dist/test/local-verification.d.ts +28 -0
  196. package/dist/test/local-verification.js +342 -0
  197. package/dist/test/mock-identity-provider.d.ts +96 -0
  198. package/dist/test/mock-identity-provider.js +243 -0
  199. package/dist/test/runtime-integration.d.ts +63 -0
  200. package/dist/test/runtime-integration.js +140 -0
  201. package/dist/test/test-environment.d.ts +26 -0
  202. package/dist/test/test-environment.js +50 -0
  203. package/dist/types/declarations.d.ts +1 -0
  204. package/dist/types/declarations.js +6 -0
  205. package/dist/types/middleware.d.ts +2 -0
  206. package/dist/types/middleware.js +2 -0
  207. package/dist/types/tool.d.ts +80 -0
  208. package/dist/types/tool.js +2 -0
  209. package/dist/utils/cli-icons.d.ts +3 -0
  210. package/dist/utils/cli-icons.js +7 -0
  211. package/dist/utils/constants.d.ts +6 -0
  212. package/dist/utils/constants.js +13 -0
  213. package/dist/utils/context.d.ts +33 -0
  214. package/dist/utils/context.js +58 -0
  215. package/dist/utils/file-watcher.d.ts +19 -0
  216. package/dist/utils/file-watcher.js +49 -0
  217. package/dist/utils/fs-utils.d.ts +2 -0
  218. package/dist/utils/fs-utils.js +22 -0
  219. package/dist/utils/path-validation.d.ts +3 -0
  220. package/dist/utils/path-validation.js +56 -0
  221. package/dist/utils/spawn-process.d.ts +9 -0
  222. package/dist/utils/spawn-process.js +50 -0
  223. package/dist/utils/subscribable.d.ts +12 -0
  224. package/dist/utils/subscribable.js +44 -0
  225. package/package.json +91 -77
  226. package/dist/cjs/auto.js +0 -16
  227. package/dist/cjs/cli-mode.d.ts +0 -16
  228. package/dist/cjs/cli-mode.js +0 -32
  229. package/dist/cjs/crypto.d.ts +0 -16
  230. package/dist/cjs/crypto.js +0 -212
  231. package/dist/cjs/dev-helper.d.ts +0 -3
  232. package/dist/cjs/dev-helper.js +0 -46
  233. package/dist/cjs/encrypted-storage.d.ts +0 -11
  234. package/dist/cjs/encrypted-storage.js +0 -73
  235. package/dist/cjs/index.d.ts +0 -56
  236. package/dist/cjs/index.js +0 -727
  237. package/dist/cjs/logger.d.ts +0 -32
  238. package/dist/cjs/logger.js +0 -85
  239. package/dist/cjs/nextjs.d.ts +0 -10
  240. package/dist/cjs/nextjs.js +0 -83
  241. package/dist/cjs/platform-info.d.ts +0 -36
  242. package/dist/cjs/platform-info.js +0 -274
  243. package/dist/cjs/polling.d.ts +0 -13
  244. package/dist/cjs/polling.js +0 -52
  245. package/dist/cjs/registry/index.d.ts +0 -12
  246. package/dist/cjs/registry/index.js +0 -56
  247. package/dist/cjs/registry/knowthat.d.ts +0 -17
  248. package/dist/cjs/registry/knowthat.js +0 -173
  249. package/dist/cjs/rotation.d.ts +0 -35
  250. package/dist/cjs/rotation.js +0 -102
  251. package/dist/cjs/storage.d.ts +0 -41
  252. package/dist/cjs/storage.js +0 -163
  253. package/dist/cjs/transport.d.ts +0 -35
  254. package/dist/cjs/transport.js +0 -300
  255. package/dist/cjs/types.d.ts +0 -206
  256. package/dist/cjs/vercel-adapter.d.ts +0 -8
  257. package/dist/cjs/vercel-adapter.js +0 -67
  258. package/dist/esm/auto.d.ts +0 -13
  259. package/dist/esm/auto.d.ts.map +0 -1
  260. package/dist/esm/auto.js +0 -30
  261. package/dist/esm/auto.js.map +0 -1
  262. package/dist/esm/cli-mode.d.ts +0 -52
  263. package/dist/esm/cli-mode.d.ts.map +0 -1
  264. package/dist/esm/cli-mode.js +0 -59
  265. package/dist/esm/cli-mode.js.map +0 -1
  266. package/dist/esm/crypto.d.ts +0 -51
  267. package/dist/esm/crypto.d.ts.map +0 -1
  268. package/dist/esm/crypto.js +0 -230
  269. package/dist/esm/crypto.js.map +0 -1
  270. package/dist/esm/dev-helper.d.ts +0 -15
  271. package/dist/esm/dev-helper.d.ts.map +0 -1
  272. package/dist/esm/dev-helper.js +0 -63
  273. package/dist/esm/dev-helper.js.map +0 -1
  274. package/dist/esm/encrypted-storage.d.ts +0 -19
  275. package/dist/esm/encrypted-storage.d.ts.map +0 -1
  276. package/dist/esm/encrypted-storage.js +0 -48
  277. package/dist/esm/encrypted-storage.js.map +0 -1
  278. package/dist/esm/index.d.ts +0 -129
  279. package/dist/esm/index.d.ts.map +0 -1
  280. package/dist/esm/index.js +0 -853
  281. package/dist/esm/index.js.map +0 -1
  282. package/dist/esm/logger.d.ts +0 -46
  283. package/dist/esm/logger.d.ts.map +0 -1
  284. package/dist/esm/logger.js +0 -100
  285. package/dist/esm/logger.js.map +0 -1
  286. package/dist/esm/nextjs.d.ts +0 -22
  287. package/dist/esm/nextjs.d.ts.map +0 -1
  288. package/dist/esm/nextjs.js +0 -83
  289. package/dist/esm/nextjs.js.map +0 -1
  290. package/dist/esm/package.json +0 -1
  291. package/dist/esm/platform-info.d.ts +0 -74
  292. package/dist/esm/platform-info.d.ts.map +0 -1
  293. package/dist/esm/platform-info.js +0 -293
  294. package/dist/esm/platform-info.js.map +0 -1
  295. package/dist/esm/polling.d.ts +0 -29
  296. package/dist/esm/polling.d.ts.map +0 -1
  297. package/dist/esm/polling.js +0 -76
  298. package/dist/esm/polling.js.map +0 -1
  299. package/dist/esm/registry/index.d.ts +0 -43
  300. package/dist/esm/registry/index.d.ts.map +0 -1
  301. package/dist/esm/registry/index.js +0 -89
  302. package/dist/esm/registry/index.js.map +0 -1
  303. package/dist/esm/registry/knowthat.d.ts +0 -44
  304. package/dist/esm/registry/knowthat.d.ts.map +0 -1
  305. package/dist/esm/registry/knowthat.js +0 -220
  306. package/dist/esm/registry/knowthat.js.map +0 -1
  307. package/dist/esm/rotation.d.ts +0 -57
  308. package/dist/esm/rotation.d.ts.map +0 -1
  309. package/dist/esm/rotation.js +0 -133
  310. package/dist/esm/rotation.js.map +0 -1
  311. package/dist/esm/storage.d.ts +0 -65
  312. package/dist/esm/storage.d.ts.map +0 -1
  313. package/dist/esm/storage.js +0 -160
  314. package/dist/esm/storage.js.map +0 -1
  315. package/dist/esm/transport.d.ts +0 -52
  316. package/dist/esm/transport.d.ts.map +0 -1
  317. package/dist/esm/transport.js +0 -340
  318. package/dist/esm/transport.js.map +0 -1
  319. package/dist/esm/types.d.ts +0 -293
  320. package/dist/esm/types.d.ts.map +0 -1
  321. package/dist/esm/types.js +0 -5
  322. package/dist/esm/types.js.map +0 -1
  323. package/dist/esm/vercel-adapter.d.ts +0 -26
  324. package/dist/esm/vercel-adapter.d.ts.map +0 -1
  325. package/dist/esm/vercel-adapter.js +0 -80
  326. package/dist/esm/vercel-adapter.js.map +0 -1
  327. /package/dist/{cjs → auth/oauth}/types.js +0 -0
  328. /package/dist/{cjs/auto.d.ts → runtime/transports/http/index.d.ts} +0 -0
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CloudflareKVNonceCache = void 0;
4
+ /**
5
+ * Cloudflare KV-based nonce cache implementation
6
+ * Suitable for Cloudflare Workers deployments
7
+ */
8
+ class CloudflareKVNonceCache {
9
+ kv; // KV namespace - type depends on Cloudflare Workers runtime
10
+ keyPrefix;
11
+ constructor(kv, keyPrefix = "nonce:") {
12
+ this.kv = kv;
13
+ this.keyPrefix = keyPrefix;
14
+ }
15
+ getKey(nonce) {
16
+ return `${this.keyPrefix}${nonce}`;
17
+ }
18
+ async has(nonce) {
19
+ const key = this.getKey(nonce);
20
+ const value = await this.kv.get(key);
21
+ if (!value) {
22
+ return false;
23
+ }
24
+ // Parse the stored data to check expiry
25
+ try {
26
+ const data = JSON.parse(value);
27
+ if (Date.now() > data.expiresAt) {
28
+ // Clean up expired entry
29
+ await this.kv.delete(key);
30
+ return false;
31
+ }
32
+ return true;
33
+ }
34
+ catch {
35
+ // If we can't parse, assume expired and clean up
36
+ await this.kv.delete(key);
37
+ return false;
38
+ }
39
+ }
40
+ async add(nonce, ttl) {
41
+ const key = this.getKey(nonce);
42
+ const expiresAt = Date.now() + ttl * 1000;
43
+ const data = {
44
+ nonce,
45
+ expiresAt,
46
+ createdAt: Date.now(),
47
+ };
48
+ // Cloudflare KV doesn't have native atomic add-if-absent
49
+ // We implement a best-effort approach with metadata checking
50
+ try {
51
+ // First, try to get the existing value with metadata
52
+ const existingWithMetadata = await this.kv.getWithMetadata(key);
53
+ if (existingWithMetadata && existingWithMetadata.value !== null) {
54
+ // Key exists, check if it's still valid
55
+ try {
56
+ const existingData = JSON.parse(existingWithMetadata.value);
57
+ if (Date.now() <= existingData.expiresAt) {
58
+ throw new Error(`Nonce ${nonce} already exists - potential replay attack`);
59
+ }
60
+ // If expired, we can proceed to overwrite
61
+ }
62
+ catch {
63
+ // If we can't parse existing data, assume it's corrupted and overwrite
64
+ }
65
+ }
66
+ // Store with KV TTL as backup (convert to seconds)
67
+ await this.kv.put(key, JSON.stringify(data), {
68
+ expirationTtl: ttl,
69
+ });
70
+ }
71
+ catch (error) {
72
+ // If getWithMetadata is not available, fall back to basic approach
73
+ if (error.message?.includes("getWithMetadata")) {
74
+ // Check if already exists first (less atomic but still functional)
75
+ if (await this.has(nonce)) {
76
+ throw new Error(`Nonce ${nonce} already exists - potential replay attack`);
77
+ }
78
+ // Store with KV TTL as backup (convert to seconds)
79
+ await this.kv.put(key, JSON.stringify(data), {
80
+ expirationTtl: ttl,
81
+ });
82
+ }
83
+ else {
84
+ throw error;
85
+ }
86
+ }
87
+ }
88
+ async cleanup() {
89
+ // Cloudflare KV handles expiry automatically via TTL, so this is a no-op
90
+ // This method exists to satisfy the interface
91
+ }
92
+ }
93
+ exports.CloudflareKVNonceCache = CloudflareKVNonceCache;
@@ -0,0 +1,15 @@
1
+ import { NonceCache } from "@kya-os/contracts/handshake";
2
+ /**
3
+ * DynamoDB-based nonce cache implementation
4
+ * Suitable for AWS Lambda deployments
5
+ */
6
+ export declare class DynamoNonceCache implements NonceCache {
7
+ private dynamodb;
8
+ private tableName;
9
+ private keyAttribute;
10
+ private ttlAttribute;
11
+ constructor(dynamodb: any, tableName: string, keyAttribute?: string, ttlAttribute?: string);
12
+ has(nonce: string): Promise<boolean>;
13
+ add(nonce: string, ttl: number): Promise<void>;
14
+ cleanup(): Promise<void>;
15
+ }
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DynamoNonceCache = void 0;
4
+ /**
5
+ * DynamoDB-based nonce cache implementation
6
+ * Suitable for AWS Lambda deployments
7
+ */
8
+ class DynamoNonceCache {
9
+ dynamodb; // DynamoDB client - type depends on AWS SDK version
10
+ tableName;
11
+ keyAttribute;
12
+ ttlAttribute;
13
+ constructor(dynamodb, tableName, keyAttribute = "nonce", ttlAttribute = "expiresAt") {
14
+ this.dynamodb = dynamodb;
15
+ this.tableName = tableName;
16
+ this.keyAttribute = keyAttribute;
17
+ this.ttlAttribute = ttlAttribute;
18
+ }
19
+ async has(nonce) {
20
+ try {
21
+ const result = await this.dynamodb
22
+ .getItem({
23
+ TableName: this.tableName,
24
+ Key: {
25
+ [this.keyAttribute]: { S: nonce },
26
+ },
27
+ ConsistentRead: true, // Ensure we get the latest data
28
+ })
29
+ .promise();
30
+ if (!result.Item) {
31
+ return false;
32
+ }
33
+ // Check if expired (DynamoDB TTL might not have cleaned up yet)
34
+ const expiresAt = parseInt(result.Item[this.ttlAttribute].N);
35
+ if (Date.now() / 1000 > expiresAt) {
36
+ return false;
37
+ }
38
+ return true;
39
+ }
40
+ catch (error) {
41
+ // Log error but don't expose internal details
42
+ console.error("DynamoDB has() operation failed:", error);
43
+ // For certain errors, we can safely return false
44
+ if (error.code === "ResourceNotFoundException" ||
45
+ error.code === "ItemCollectionSizeLimitExceededException") {
46
+ return false;
47
+ }
48
+ // For other errors, we should throw to avoid security issues
49
+ throw new Error(`Failed to check nonce existence: ${error.code || error.message}`);
50
+ }
51
+ }
52
+ async add(nonce, ttl) {
53
+ const expiresAt = Math.floor(Date.now() / 1000) + ttl;
54
+ try {
55
+ // Use conditional write to ensure atomic add-if-absent
56
+ // This is truly atomic in DynamoDB
57
+ await this.dynamodb
58
+ .putItem({
59
+ TableName: this.tableName,
60
+ Item: {
61
+ [this.keyAttribute]: { S: nonce },
62
+ [this.ttlAttribute]: { N: expiresAt.toString() },
63
+ createdAt: { N: Math.floor(Date.now() / 1000).toString() },
64
+ },
65
+ ConditionExpression: `attribute_not_exists(${this.keyAttribute})`,
66
+ })
67
+ .promise();
68
+ }
69
+ catch (error) {
70
+ if (error.code === "ConditionalCheckFailedException") {
71
+ throw new Error(`Nonce ${nonce} already exists - potential replay attack`);
72
+ }
73
+ console.error("DynamoDB add() operation failed:", error);
74
+ // Provide more specific error messages for common issues
75
+ if (error.code === "ResourceNotFoundException") {
76
+ throw new Error(`DynamoDB table ${this.tableName} not found`);
77
+ }
78
+ else if (error.code === "ValidationException") {
79
+ throw new Error(`Invalid DynamoDB operation: ${error.message}`);
80
+ }
81
+ else if (error.code === "ProvisionedThroughputExceededException") {
82
+ throw new Error("DynamoDB throughput exceeded - consider increasing capacity");
83
+ }
84
+ throw new Error(`Failed to add nonce to cache: ${error.code || error.message}`);
85
+ }
86
+ }
87
+ async cleanup() {
88
+ // DynamoDB handles TTL cleanup automatically, so this is a no-op
89
+ // This method exists to satisfy the interface
90
+ }
91
+ }
92
+ exports.DynamoNonceCache = DynamoNonceCache;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Pluggable nonce cache architecture for XMCP-I
3
+ *
4
+ * Provides replay prevention through various cache backends:
5
+ * - Memory (development, single instance)
6
+ * - Redis (production, multi-instance)
7
+ * - DynamoDB (AWS Lambda)
8
+ * - Cloudflare KV (Cloudflare Workers)
9
+ */
10
+ export type { SessionContext, HandshakeRequest, NonceCacheEntry, NonceCache, NonceCacheConfig, } from "@kya-os/contracts/handshake";
11
+ export { SessionContextSchema, HandshakeRequestSchema, NonceCacheEntrySchema, NonceCacheConfigSchema, } from "@kya-os/contracts/handshake";
12
+ export { MemoryNonceCache } from "./memory-nonce-cache";
13
+ export { RedisNonceCache } from "./redis-nonce-cache";
14
+ export { DynamoNonceCache } from "./dynamodb-nonce-cache";
15
+ export { CloudflareKVNonceCache } from "./cloudflare-kv-nonce-cache";
16
+ export { createNonceCache, createNonceCacheWithConfig, detectCacheType, type NonceCacheOptions, } from "./nonce-cache-factory";
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ /**
3
+ * Pluggable nonce cache architecture for XMCP-I
4
+ *
5
+ * Provides replay prevention through various cache backends:
6
+ * - Memory (development, single instance)
7
+ * - Redis (production, multi-instance)
8
+ * - DynamoDB (AWS Lambda)
9
+ * - Cloudflare KV (Cloudflare Workers)
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.detectCacheType = exports.createNonceCacheWithConfig = exports.createNonceCache = exports.CloudflareKVNonceCache = exports.DynamoNonceCache = exports.RedisNonceCache = exports.MemoryNonceCache = exports.NonceCacheConfigSchema = exports.NonceCacheEntrySchema = exports.HandshakeRequestSchema = exports.SessionContextSchema = void 0;
13
+ // Re-export schemas
14
+ var handshake_1 = require("@kya-os/contracts/handshake");
15
+ Object.defineProperty(exports, "SessionContextSchema", { enumerable: true, get: function () { return handshake_1.SessionContextSchema; } });
16
+ Object.defineProperty(exports, "HandshakeRequestSchema", { enumerable: true, get: function () { return handshake_1.HandshakeRequestSchema; } });
17
+ Object.defineProperty(exports, "NonceCacheEntrySchema", { enumerable: true, get: function () { return handshake_1.NonceCacheEntrySchema; } });
18
+ Object.defineProperty(exports, "NonceCacheConfigSchema", { enumerable: true, get: function () { return handshake_1.NonceCacheConfigSchema; } });
19
+ // Cache implementations
20
+ var memory_nonce_cache_1 = require("./memory-nonce-cache");
21
+ Object.defineProperty(exports, "MemoryNonceCache", { enumerable: true, get: function () { return memory_nonce_cache_1.MemoryNonceCache; } });
22
+ var redis_nonce_cache_1 = require("./redis-nonce-cache");
23
+ Object.defineProperty(exports, "RedisNonceCache", { enumerable: true, get: function () { return redis_nonce_cache_1.RedisNonceCache; } });
24
+ var dynamodb_nonce_cache_1 = require("./dynamodb-nonce-cache");
25
+ Object.defineProperty(exports, "DynamoNonceCache", { enumerable: true, get: function () { return dynamodb_nonce_cache_1.DynamoNonceCache; } });
26
+ var cloudflare_kv_nonce_cache_1 = require("./cloudflare-kv-nonce-cache");
27
+ Object.defineProperty(exports, "CloudflareKVNonceCache", { enumerable: true, get: function () { return cloudflare_kv_nonce_cache_1.CloudflareKVNonceCache; } });
28
+ // Factory and auto-detection
29
+ var nonce_cache_factory_1 = require("./nonce-cache-factory");
30
+ Object.defineProperty(exports, "createNonceCache", { enumerable: true, get: function () { return nonce_cache_factory_1.createNonceCache; } });
31
+ Object.defineProperty(exports, "createNonceCacheWithConfig", { enumerable: true, get: function () { return nonce_cache_factory_1.createNonceCacheWithConfig; } });
32
+ Object.defineProperty(exports, "detectCacheType", { enumerable: true, get: function () { return nonce_cache_factory_1.detectCacheType; } });
@@ -0,0 +1,44 @@
1
+ /**
2
+ * In-memory nonce cache implementation
3
+ *
4
+ * WARNING: This implementation is only suitable for single-instance deployments.
5
+ * For multi-instance deployments, use Redis, DynamoDB, or Cloudflare KV implementations.
6
+ */
7
+ import { NonceCache } from "@kya-os/contracts/handshake";
8
+ /**
9
+ * In-memory nonce cache with TTL support
10
+ */
11
+ export declare class MemoryNonceCache implements NonceCache {
12
+ private cache;
13
+ private cleanupInterval?;
14
+ constructor(cleanupIntervalMs?: number);
15
+ /**
16
+ * Check if a nonce exists in the cache
17
+ */
18
+ has(nonce: string): Promise<boolean>;
19
+ /**
20
+ * Add a nonce to the cache with TTL
21
+ * MUST ensure atomic add-if-absent semantics for replay prevention
22
+ */
23
+ add(nonce: string, ttlSeconds: number): Promise<void>;
24
+ /**
25
+ * Clean up expired entries
26
+ * Safe to call frequently and should be no-op for backends that auto-expire
27
+ */
28
+ cleanup(): Promise<void>;
29
+ /**
30
+ * Get cache statistics
31
+ */
32
+ getStats(): {
33
+ size: number;
34
+ expired: number;
35
+ };
36
+ /**
37
+ * Clear all entries (useful for testing)
38
+ */
39
+ clear(): void;
40
+ /**
41
+ * Destroy the cache and stop cleanup interval
42
+ */
43
+ destroy(): void;
44
+ }
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ /**
3
+ * In-memory nonce cache implementation
4
+ *
5
+ * WARNING: This implementation is only suitable for single-instance deployments.
6
+ * For multi-instance deployments, use Redis, DynamoDB, or Cloudflare KV implementations.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.MemoryNonceCache = void 0;
10
+ /**
11
+ * In-memory nonce cache with TTL support
12
+ */
13
+ class MemoryNonceCache {
14
+ cache = new Map();
15
+ cleanupInterval;
16
+ constructor(cleanupIntervalMs = 60000) {
17
+ // Default: 1 minute cleanup
18
+ // Start periodic cleanup
19
+ this.cleanupInterval = setInterval(() => {
20
+ this.cleanup().catch(console.error);
21
+ }, cleanupIntervalMs);
22
+ }
23
+ /**
24
+ * Check if a nonce exists in the cache
25
+ */
26
+ async has(nonce) {
27
+ const entry = this.cache.get(nonce);
28
+ if (!entry) {
29
+ return false;
30
+ }
31
+ // Check if expired
32
+ if (Date.now() > entry.expiresAt) {
33
+ this.cache.delete(nonce);
34
+ return false;
35
+ }
36
+ return true;
37
+ }
38
+ /**
39
+ * Add a nonce to the cache with TTL
40
+ * MUST ensure atomic add-if-absent semantics for replay prevention
41
+ */
42
+ async add(nonce, ttlSeconds) {
43
+ // Check if nonce already exists (atomic check-and-set)
44
+ const existing = this.cache.get(nonce);
45
+ if (existing && Date.now() <= existing.expiresAt) {
46
+ throw new Error(`Nonce ${nonce} already exists`);
47
+ }
48
+ // Handle zero or negative TTL - set expiration to past time
49
+ const expiresAt = ttlSeconds <= 0 ? Date.now() - 1 : Date.now() + ttlSeconds * 1000;
50
+ const entry = {
51
+ sessionId: `mem_${Date.now()}_${Math.random().toString(36).substring(2)}`,
52
+ expiresAt,
53
+ };
54
+ this.cache.set(nonce, entry);
55
+ }
56
+ /**
57
+ * Clean up expired entries
58
+ * Safe to call frequently and should be no-op for backends that auto-expire
59
+ */
60
+ async cleanup() {
61
+ const now = Date.now();
62
+ const expiredKeys = [];
63
+ for (const [nonce, entry] of this.cache.entries()) {
64
+ if (now > entry.expiresAt) {
65
+ expiredKeys.push(nonce);
66
+ }
67
+ }
68
+ for (const key of expiredKeys) {
69
+ this.cache.delete(key);
70
+ }
71
+ }
72
+ /**
73
+ * Get cache statistics
74
+ */
75
+ getStats() {
76
+ const now = Date.now();
77
+ let expired = 0;
78
+ for (const entry of this.cache.values()) {
79
+ if (now > entry.expiresAt) {
80
+ expired++;
81
+ }
82
+ }
83
+ return {
84
+ size: this.cache.size,
85
+ expired,
86
+ };
87
+ }
88
+ /**
89
+ * Clear all entries (useful for testing)
90
+ */
91
+ clear() {
92
+ this.cache.clear();
93
+ }
94
+ /**
95
+ * Destroy the cache and stop cleanup interval
96
+ */
97
+ destroy() {
98
+ if (this.cleanupInterval) {
99
+ clearInterval(this.cleanupInterval);
100
+ this.cleanupInterval = undefined;
101
+ }
102
+ this.cache.clear();
103
+ }
104
+ }
105
+ exports.MemoryNonceCache = MemoryNonceCache;
@@ -0,0 +1,20 @@
1
+ import { NonceCache, NonceCacheConfig } from "@kya-os/contracts/handshake";
2
+ /**
3
+ * Environment-based cache type detection
4
+ */
5
+ export declare function detectCacheType(): "memory" | "redis" | "dynamodb" | "cloudflare-kv";
6
+ /**
7
+ * Create a nonce cache instance based on configuration or environment detection
8
+ */
9
+ export declare function createNonceCache(config?: NonceCacheConfig): Promise<NonceCache>;
10
+ /**
11
+ * Configuration override options for nonce cache
12
+ */
13
+ export interface NonceCacheOptions {
14
+ config?: NonceCacheConfig;
15
+ fallbackToMemory?: boolean;
16
+ }
17
+ /**
18
+ * Create nonce cache with explicit configuration override
19
+ */
20
+ export declare function createNonceCacheWithConfig(options?: NonceCacheOptions): Promise<NonceCache>;
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectCacheType = detectCacheType;
4
+ exports.createNonceCache = createNonceCache;
5
+ exports.createNonceCacheWithConfig = createNonceCacheWithConfig;
6
+ const memory_nonce_cache_1 = require("./memory-nonce-cache");
7
+ const redis_nonce_cache_1 = require("./redis-nonce-cache");
8
+ const dynamodb_nonce_cache_1 = require("./dynamodb-nonce-cache");
9
+ const cloudflare_kv_nonce_cache_1 = require("./cloudflare-kv-nonce-cache");
10
+ /**
11
+ * Get environment variable with fallback support for old naming
12
+ * Supports migration from XMCPI_ to MCPI_ prefixes
13
+ */
14
+ function getEnvWithFallback(newKey, oldKey) {
15
+ const newValue = process.env[newKey];
16
+ if (newValue !== undefined) {
17
+ return newValue;
18
+ }
19
+ if (oldKey) {
20
+ const oldValue = process.env[oldKey];
21
+ if (oldValue !== undefined) {
22
+ console.warn(`⚠️ Environment variable ${oldKey} is deprecated. Please use ${newKey} instead.`);
23
+ return oldValue;
24
+ }
25
+ }
26
+ return undefined;
27
+ }
28
+ /**
29
+ * Environment-based cache type detection
30
+ */
31
+ function detectCacheType() {
32
+ // Check for explicit configuration (with fallback support)
33
+ const explicitType = getEnvWithFallback("MCPI_NONCE_CACHE_TYPE", "XMCPI_NONCE_CACHE_TYPE");
34
+ if (explicitType &&
35
+ ["memory", "redis", "dynamodb", "cloudflare-kv"].includes(explicitType)) {
36
+ return explicitType;
37
+ }
38
+ // Auto-detect based on environment (most specific first)
39
+ // Redis detection
40
+ if (process.env.REDIS_URL ||
41
+ getEnvWithFallback("MCPI_REDIS_URL", "XMCPI_REDIS_URL")) {
42
+ return "redis";
43
+ }
44
+ // DynamoDB detection (AWS Lambda environment)
45
+ if ((process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION) &&
46
+ getEnvWithFallback("MCPI_DYNAMODB_TABLE", "XMCPI_DYNAMODB_TABLE")) {
47
+ return "dynamodb";
48
+ }
49
+ // Cloudflare Workers detection (more robust)
50
+ if (typeof globalThis !== "undefined") {
51
+ // Check for Cloudflare Workers specific globals
52
+ const globalScope = globalThis;
53
+ if ("caches" in globalThis &&
54
+ typeof globalScope.fetch === "function" &&
55
+ (typeof globalScope.addEventListener === "function" ||
56
+ typeof globalScope.Response === "function")) {
57
+ return "cloudflare-kv";
58
+ }
59
+ }
60
+ // Warn about memory cache in production
61
+ if (process.env.NODE_ENV === "production" ||
62
+ getEnvWithFallback("MCPI_ENV", "XMCPI_ENV") === "production") {
63
+ console.warn("mcpi: Using memory cache in production environment. " +
64
+ "For multi-instance deployments, configure Redis (REDIS_URL), " +
65
+ "DynamoDB (AWS_REGION + MCPI_DYNAMODB_TABLE), or " +
66
+ "Cloudflare KV (MCPI_KV_NAMESPACE).");
67
+ }
68
+ return "memory";
69
+ }
70
+ /**
71
+ * Create a nonce cache instance based on configuration or environment detection
72
+ */
73
+ async function createNonceCache(config) {
74
+ const cacheType = config?.type || detectCacheType();
75
+ switch (cacheType) {
76
+ case "redis": {
77
+ const redisUrl = config?.redis?.url ||
78
+ process.env.REDIS_URL ||
79
+ getEnvWithFallback("MCPI_REDIS_URL", "XMCPI_REDIS_URL");
80
+ if (!redisUrl) {
81
+ console.warn("Redis URL not found, falling back to memory cache");
82
+ return new memory_nonce_cache_1.MemoryNonceCache();
83
+ }
84
+ try {
85
+ // Dynamic import to avoid bundling Redis in environments that don't need it
86
+ const { createClient } = await import("redis");
87
+ const redis = createClient({
88
+ url: redisUrl,
89
+ socket: {
90
+ connectTimeout: 5000, // 5 second timeout
91
+ },
92
+ });
93
+ // Test connection
94
+ await redis.connect();
95
+ // Verify basic operations work
96
+ await redis.ping();
97
+ return new redis_nonce_cache_1.RedisNonceCache(redis, config?.redis?.keyPrefix);
98
+ }
99
+ catch (error) {
100
+ const errorMessage = error instanceof Error ? error.message : String(error);
101
+ console.warn("Failed to connect to Redis, falling back to memory cache:", errorMessage);
102
+ return new memory_nonce_cache_1.MemoryNonceCache();
103
+ }
104
+ }
105
+ case "dynamodb": {
106
+ const tableName = config?.dynamodb?.tableName ||
107
+ getEnvWithFallback("MCPI_DYNAMODB_TABLE", "XMCPI_DYNAMODB_TABLE");
108
+ if (!tableName) {
109
+ console.warn("DynamoDB table name not found, falling back to memory cache");
110
+ return new memory_nonce_cache_1.MemoryNonceCache();
111
+ }
112
+ try {
113
+ // Dynamic import to avoid bundling AWS SDK in environments that don't need it
114
+ const awsSdk = await import("@aws-sdk/client-dynamodb");
115
+ // Extract types from dynamic import - handle both ESM and CJS exports
116
+ const DynamoDBClient = awsSdk.DynamoDBClient ||
117
+ awsSdk.default?.DynamoDBClient;
118
+ const DescribeTableCommand = awsSdk.DescribeTableCommand ||
119
+ awsSdk.default?.DescribeTableCommand;
120
+ const region = config?.dynamodb?.region ||
121
+ process.env.AWS_REGION ||
122
+ process.env.AWS_DEFAULT_REGION ||
123
+ "us-east-1";
124
+ const dynamodb = new DynamoDBClient({
125
+ region,
126
+ maxAttempts: 3,
127
+ });
128
+ // Verify table exists and is accessible
129
+ try {
130
+ await dynamodb.send(new DescribeTableCommand({ TableName: tableName }));
131
+ }
132
+ catch (tableError) {
133
+ const error = tableError;
134
+ if (error.name === "ResourceNotFoundException") {
135
+ throw new Error(`DynamoDB table '${tableName}' not found in region '${region}'`);
136
+ }
137
+ throw tableError;
138
+ }
139
+ return new dynamodb_nonce_cache_1.DynamoNonceCache(dynamodb, tableName, config?.dynamodb?.keyAttribute, config?.dynamodb?.ttlAttribute);
140
+ }
141
+ catch (error) {
142
+ const errorMessage = error instanceof Error ? error.message : String(error);
143
+ console.warn("Failed to initialize DynamoDB, falling back to memory cache:", errorMessage);
144
+ return new memory_nonce_cache_1.MemoryNonceCache();
145
+ }
146
+ }
147
+ case "cloudflare-kv": {
148
+ const namespace = config?.cloudflareKv?.namespace ||
149
+ getEnvWithFallback("MCPI_KV_NAMESPACE", "XMCPI_KV_NAMESPACE");
150
+ if (!namespace) {
151
+ console.warn("Cloudflare KV namespace not found, falling back to memory cache");
152
+ return new memory_nonce_cache_1.MemoryNonceCache();
153
+ }
154
+ try {
155
+ // In Cloudflare Workers, KV namespaces are available as globals
156
+ const globalScope = globalThis;
157
+ const kv = globalScope[namespace];
158
+ if (!kv) {
159
+ throw new Error(`KV namespace '${namespace}' not found in global scope`);
160
+ }
161
+ // Verify KV namespace has required methods
162
+ const kvInterface = kv;
163
+ if (typeof kvInterface.get !== "function" ||
164
+ typeof kvInterface.put !== "function") {
165
+ throw new Error(`KV namespace '${namespace}' does not have required methods`);
166
+ }
167
+ // Test basic KV operation (this will be very fast in Workers)
168
+ try {
169
+ const kvInterface = kv;
170
+ await kvInterface.get("__mcpi_test_key__");
171
+ }
172
+ catch (kvError) {
173
+ const error = kvError;
174
+ // Some KV errors are expected (like key not found), but connection errors are not
175
+ if (error.message?.includes("network") ||
176
+ error.message?.includes("timeout")) {
177
+ throw kvError;
178
+ }
179
+ // Other errors (like key not found) are fine
180
+ }
181
+ return new cloudflare_kv_nonce_cache_1.CloudflareKVNonceCache(kv, config?.cloudflareKv?.keyPrefix);
182
+ }
183
+ catch (error) {
184
+ const errorMessage = error instanceof Error ? error.message : String(error);
185
+ console.warn("Failed to initialize Cloudflare KV, falling back to memory cache:", errorMessage);
186
+ return new memory_nonce_cache_1.MemoryNonceCache();
187
+ }
188
+ }
189
+ case "memory":
190
+ default:
191
+ return new memory_nonce_cache_1.MemoryNonceCache();
192
+ }
193
+ }
194
+ /**
195
+ * Create nonce cache with explicit configuration override
196
+ */
197
+ async function createNonceCacheWithConfig(options = {}) {
198
+ try {
199
+ return await createNonceCache(options.config);
200
+ }
201
+ catch (error) {
202
+ if (options.fallbackToMemory !== false) {
203
+ console.warn("Failed to create configured nonce cache, falling back to memory:", error);
204
+ return new memory_nonce_cache_1.MemoryNonceCache();
205
+ }
206
+ throw error;
207
+ }
208
+ }
@@ -0,0 +1,14 @@
1
+ import { NonceCache } from "@kya-os/contracts/handshake";
2
+ /**
3
+ * Redis-based nonce cache implementation
4
+ * Suitable for multi-instance deployments
5
+ */
6
+ export declare class RedisNonceCache implements NonceCache {
7
+ private redis;
8
+ private keyPrefix;
9
+ constructor(redis: any, keyPrefix?: string);
10
+ private getKey;
11
+ has(nonce: string): Promise<boolean>;
12
+ add(nonce: string, ttl: number): Promise<void>;
13
+ cleanup(): Promise<void>;
14
+ }