@labacacia/nps-sdk 1.0.0-alpha.6 → 1.0.0-alpha.8

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 (369) hide show
  1. package/CHANGELOG.cn.md +126 -0
  2. package/CHANGELOG.md +135 -0
  3. package/README.cn.md +9 -2
  4. package/README.md +9 -2
  5. package/dist/core/anchor-cache.d.ts +42 -0
  6. package/dist/core/anchor-cache.d.ts.map +1 -0
  7. package/dist/core/anchor-cache.js +104 -0
  8. package/dist/core/anchor-cache.js.map +1 -0
  9. package/dist/core/cache.d.ts +14 -0
  10. package/dist/core/cache.d.ts.map +1 -0
  11. package/dist/core/cache.js +80 -0
  12. package/dist/core/cache.js.map +1 -0
  13. package/dist/core/canonical-json.d.ts +12 -0
  14. package/dist/core/canonical-json.d.ts.map +1 -0
  15. package/dist/core/canonical-json.js +44 -0
  16. package/dist/core/canonical-json.js.map +1 -0
  17. package/dist/core/codec.d.ts +32 -0
  18. package/dist/core/codec.d.ts.map +1 -0
  19. package/dist/core/codec.js +119 -0
  20. package/dist/core/codec.js.map +1 -0
  21. package/dist/core/codecs/index.d.ts +4 -0
  22. package/dist/core/codecs/index.d.ts.map +1 -0
  23. package/{src/core/codecs/index.ts → dist/core/codecs/index.js} +1 -0
  24. package/dist/core/codecs/index.js.map +1 -0
  25. package/dist/core/codecs/ncp-codec.d.ts +39 -0
  26. package/dist/core/codecs/ncp-codec.d.ts.map +1 -0
  27. package/dist/core/codecs/ncp-codec.js +93 -0
  28. package/dist/core/codecs/ncp-codec.js.map +1 -0
  29. package/dist/core/codecs/tier1-json-codec.d.ts +10 -0
  30. package/dist/core/codecs/tier1-json-codec.d.ts.map +1 -0
  31. package/{src/core/codecs/tier1-json-codec.ts → dist/core/codecs/tier1-json-codec.js} +11 -16
  32. package/dist/core/codecs/tier1-json-codec.js.map +1 -0
  33. package/dist/core/codecs/tier2-msgpack-codec.d.ts +10 -0
  34. package/dist/core/codecs/tier2-msgpack-codec.d.ts.map +1 -0
  35. package/{src/core/codecs/tier2-msgpack-codec.ts → dist/core/codecs/tier2-msgpack-codec.js} +10 -14
  36. package/dist/core/codecs/tier2-msgpack-codec.js.map +1 -0
  37. package/dist/core/crypto-provider.d.ts +31 -0
  38. package/dist/core/crypto-provider.d.ts.map +1 -0
  39. package/dist/core/crypto-provider.js +10 -0
  40. package/dist/core/crypto-provider.js.map +1 -0
  41. package/dist/core/exceptions.d.ts +27 -0
  42. package/dist/core/exceptions.d.ts.map +1 -0
  43. package/dist/core/exceptions.js +52 -0
  44. package/dist/core/exceptions.js.map +1 -0
  45. package/dist/core/frame-header.d.ts +87 -0
  46. package/dist/core/frame-header.d.ts.map +1 -0
  47. package/dist/core/frame-header.js +185 -0
  48. package/dist/core/frame-header.js.map +1 -0
  49. package/dist/core/frame-registry.d.ts +35 -0
  50. package/dist/core/frame-registry.d.ts.map +1 -0
  51. package/dist/core/frame-registry.js +63 -0
  52. package/dist/core/frame-registry.js.map +1 -0
  53. package/dist/core/frames.d.ts +82 -0
  54. package/dist/core/frames.d.ts.map +1 -0
  55. package/dist/core/frames.js +155 -0
  56. package/dist/core/frames.js.map +1 -0
  57. package/dist/core/index.d.ts +11 -0
  58. package/dist/core/index.d.ts.map +1 -0
  59. package/{src/core/index.ts → dist/core/index.js} +3 -23
  60. package/dist/core/index.js.map +1 -0
  61. package/dist/core/registry.d.ts +11 -0
  62. package/dist/core/registry.d.ts.map +1 -0
  63. package/dist/core/registry.js +17 -0
  64. package/dist/core/registry.js.map +1 -0
  65. package/dist/core/status-codes.d.ts +29 -0
  66. package/dist/core/status-codes.d.ts.map +1 -0
  67. package/dist/core/status-codes.js +39 -0
  68. package/dist/core/status-codes.js.map +1 -0
  69. package/dist/index.d.ts +2 -0
  70. package/dist/index.d.ts.map +1 -0
  71. package/{src/index.ts → dist/index.js} +1 -1
  72. package/dist/index.js.map +1 -0
  73. package/dist/ncp/frames/anchor-frame.d.ts +29 -0
  74. package/dist/ncp/frames/anchor-frame.d.ts.map +1 -0
  75. package/dist/ncp/frames/anchor-frame.js +54 -0
  76. package/dist/ncp/frames/anchor-frame.js.map +1 -0
  77. package/dist/ncp/frames/caps-frame.d.ts +29 -0
  78. package/dist/ncp/frames/caps-frame.d.ts.map +1 -0
  79. package/dist/ncp/frames/caps-frame.js +29 -0
  80. package/dist/ncp/frames/caps-frame.js.map +1 -0
  81. package/dist/ncp/frames/diff-frame.d.ts +32 -0
  82. package/dist/ncp/frames/diff-frame.d.ts.map +1 -0
  83. package/dist/ncp/frames/diff-frame.js +37 -0
  84. package/dist/ncp/frames/diff-frame.js.map +1 -0
  85. package/dist/ncp/frames/error-frame.d.ts +16 -0
  86. package/dist/ncp/frames/error-frame.d.ts.map +1 -0
  87. package/dist/ncp/frames/error-frame.js +13 -0
  88. package/dist/ncp/frames/error-frame.js.map +1 -0
  89. package/dist/ncp/frames/hello-frame.d.ts +21 -0
  90. package/dist/ncp/frames/hello-frame.d.ts.map +1 -0
  91. package/dist/ncp/frames/hello-frame.js +25 -0
  92. package/dist/ncp/frames/hello-frame.js.map +1 -0
  93. package/dist/ncp/frames/stream-frame.d.ts +16 -0
  94. package/dist/ncp/frames/stream-frame.d.ts.map +1 -0
  95. package/dist/ncp/frames/stream-frame.js +18 -0
  96. package/dist/ncp/frames/stream-frame.js.map +1 -0
  97. package/dist/ncp/frames.d.ts +94 -0
  98. package/dist/ncp/frames.d.ts.map +1 -0
  99. package/dist/ncp/frames.js +192 -0
  100. package/dist/ncp/frames.js.map +1 -0
  101. package/dist/ncp/handshake.d.ts +30 -0
  102. package/dist/ncp/handshake.d.ts.map +1 -0
  103. package/dist/ncp/handshake.js +80 -0
  104. package/dist/ncp/handshake.js.map +1 -0
  105. package/dist/ncp/index.d.ts +12 -0
  106. package/dist/ncp/index.d.ts.map +1 -0
  107. package/{src/ncp/index.ts → dist/ncp/index.js} +1 -0
  108. package/dist/ncp/index.js.map +1 -0
  109. package/dist/ncp/ncp-error-codes.d.ts +23 -0
  110. package/dist/ncp/ncp-error-codes.d.ts.map +1 -0
  111. package/dist/ncp/ncp-error-codes.js +34 -0
  112. package/dist/ncp/ncp-error-codes.js.map +1 -0
  113. package/dist/ncp/ncp-patch-format.d.ts +7 -0
  114. package/dist/ncp/ncp-patch-format.d.ts.map +1 -0
  115. package/dist/ncp/ncp-patch-format.js +13 -0
  116. package/dist/ncp/ncp-patch-format.js.map +1 -0
  117. package/dist/ncp/preamble.d.ts +47 -0
  118. package/dist/ncp/preamble.d.ts.map +1 -0
  119. package/dist/ncp/preamble.js +74 -0
  120. package/dist/ncp/preamble.js.map +1 -0
  121. package/dist/ncp/registry.d.ts +3 -0
  122. package/dist/ncp/registry.d.ts.map +1 -0
  123. package/dist/ncp/registry.js +13 -0
  124. package/dist/ncp/registry.js.map +1 -0
  125. package/dist/ncp/stream-manager.d.ts +57 -0
  126. package/dist/ncp/stream-manager.d.ts.map +1 -0
  127. package/dist/ncp/stream-manager.js +163 -0
  128. package/dist/ncp/stream-manager.js.map +1 -0
  129. package/dist/ndp/dns-txt.d.ts +35 -0
  130. package/dist/ndp/dns-txt.d.ts.map +1 -0
  131. package/dist/ndp/dns-txt.js +67 -0
  132. package/dist/ndp/dns-txt.js.map +1 -0
  133. package/dist/ndp/frames.d.ts +56 -0
  134. package/dist/ndp/frames.d.ts.map +1 -0
  135. package/dist/ndp/frames.js +87 -0
  136. package/dist/ndp/frames.js.map +1 -0
  137. package/dist/ndp/index.d.ts +6 -0
  138. package/dist/ndp/index.d.ts.map +1 -0
  139. package/{src/ndp/index.ts → dist/ndp/index.js} +1 -1
  140. package/dist/ndp/index.js.map +1 -0
  141. package/dist/ndp/ndp-registry.d.ts +13 -0
  142. package/dist/ndp/ndp-registry.d.ts.map +1 -0
  143. package/dist/ndp/ndp-registry.js +104 -0
  144. package/dist/ndp/ndp-registry.js.map +1 -0
  145. package/dist/ndp/registry.d.ts +3 -0
  146. package/dist/ndp/registry.d.ts.map +1 -0
  147. package/dist/ndp/registry.js +10 -0
  148. package/dist/ndp/registry.js.map +1 -0
  149. package/dist/ndp/validator.d.ts +18 -0
  150. package/dist/ndp/validator.d.ts.map +1 -0
  151. package/dist/ndp/validator.js +48 -0
  152. package/dist/ndp/validator.js.map +1 -0
  153. package/dist/nip/acme/client.d.ts +31 -0
  154. package/dist/nip/acme/client.d.ts.map +1 -0
  155. package/dist/nip/acme/client.js +136 -0
  156. package/dist/nip/acme/client.js.map +1 -0
  157. package/dist/nip/acme/index.d.ts +6 -0
  158. package/dist/nip/acme/index.d.ts.map +1 -0
  159. package/{src/nip/acme/index.ts → dist/nip/acme/index.js} +1 -1
  160. package/dist/nip/acme/index.js.map +1 -0
  161. package/dist/nip/acme/jws.d.ts +31 -0
  162. package/dist/nip/acme/jws.d.ts.map +1 -0
  163. package/dist/nip/acme/jws.js +76 -0
  164. package/dist/nip/acme/jws.js.map +1 -0
  165. package/dist/nip/acme/messages.d.ts +71 -0
  166. package/dist/nip/acme/messages.d.ts.map +1 -0
  167. package/dist/nip/acme/messages.js +4 -0
  168. package/dist/nip/acme/messages.js.map +1 -0
  169. package/dist/nip/acme/server.d.ts +41 -0
  170. package/dist/nip/acme/server.d.ts.map +1 -0
  171. package/dist/nip/acme/server.js +458 -0
  172. package/dist/nip/acme/server.js.map +1 -0
  173. package/dist/nip/acme/wire.d.ts +19 -0
  174. package/dist/nip/acme/wire.d.ts.map +1 -0
  175. package/dist/nip/acme/wire.js +21 -0
  176. package/dist/nip/acme/wire.js.map +1 -0
  177. package/dist/nip/assurance-level.d.ts +19 -0
  178. package/dist/nip/assurance-level.d.ts.map +1 -0
  179. package/dist/nip/assurance-level.js +38 -0
  180. package/dist/nip/assurance-level.js.map +1 -0
  181. package/dist/nip/cert-format.d.ts +5 -0
  182. package/dist/nip/cert-format.d.ts.map +1 -0
  183. package/dist/nip/cert-format.js +6 -0
  184. package/dist/nip/cert-format.js.map +1 -0
  185. package/dist/nip/error-codes.d.ts +25 -0
  186. package/dist/nip/error-codes.d.ts.map +1 -0
  187. package/{src/nip/error-codes.ts → dist/nip/error-codes.js} +19 -25
  188. package/dist/nip/error-codes.js.map +1 -0
  189. package/dist/nip/frames.d.ts +53 -0
  190. package/dist/nip/frames.d.ts.map +1 -0
  191. package/dist/nip/frames.js +106 -0
  192. package/dist/nip/frames.js.map +1 -0
  193. package/dist/nip/identity.d.ts +18 -0
  194. package/dist/nip/identity.d.ts.map +1 -0
  195. package/dist/nip/identity.js +94 -0
  196. package/dist/nip/identity.js.map +1 -0
  197. package/dist/nip/index.d.ts +11 -0
  198. package/dist/nip/index.d.ts.map +1 -0
  199. package/{src/nip/index.ts → dist/nip/index.js} +3 -2
  200. package/dist/nip/index.js.map +1 -0
  201. package/dist/nip/registry.d.ts +3 -0
  202. package/dist/nip/registry.d.ts.map +1 -0
  203. package/dist/nip/registry.js +10 -0
  204. package/dist/nip/registry.js.map +1 -0
  205. package/dist/nip/reputation-client.d.ts +116 -0
  206. package/dist/nip/reputation-client.d.ts.map +1 -0
  207. package/dist/nip/reputation-client.js +261 -0
  208. package/dist/nip/reputation-client.js.map +1 -0
  209. package/dist/nip/verifier.d.ts +23 -0
  210. package/dist/nip/verifier.d.ts.map +1 -0
  211. package/dist/nip/verifier.js +90 -0
  212. package/dist/nip/verifier.js.map +1 -0
  213. package/dist/nip/x509/builder.d.ts +35 -0
  214. package/dist/nip/x509/builder.d.ts.map +1 -0
  215. package/dist/nip/x509/builder.js +59 -0
  216. package/dist/nip/x509/builder.js.map +1 -0
  217. package/dist/nip/x509/index.d.ts +4 -0
  218. package/dist/nip/x509/index.d.ts.map +1 -0
  219. package/{src/nip/x509/index.ts → dist/nip/x509/index.js} +1 -1
  220. package/dist/nip/x509/index.js.map +1 -0
  221. package/dist/nip/x509/oids.d.ts +16 -0
  222. package/dist/nip/x509/oids.d.ts.map +1 -0
  223. package/{src/nip/x509/oids.ts → dist/nip/x509/oids.js} +5 -10
  224. package/dist/nip/x509/oids.js.map +1 -0
  225. package/dist/nip/x509/verifier.d.ts +26 -0
  226. package/dist/nip/x509/verifier.d.ts.map +1 -0
  227. package/dist/nip/x509/verifier.js +171 -0
  228. package/dist/nip/x509/verifier.js.map +1 -0
  229. package/dist/nop/client.d.ts +34 -0
  230. package/dist/nop/client.d.ts.map +1 -0
  231. package/dist/nop/client.js +90 -0
  232. package/dist/nop/client.js.map +1 -0
  233. package/dist/nop/frames.d.ts +65 -0
  234. package/dist/nop/frames.d.ts.map +1 -0
  235. package/dist/nop/frames.js +148 -0
  236. package/dist/nop/frames.js.map +1 -0
  237. package/dist/nop/index.d.ts +5 -0
  238. package/dist/nop/index.d.ts.map +1 -0
  239. package/{src/nop/index.ts → dist/nop/index.js} +1 -1
  240. package/dist/nop/index.js.map +1 -0
  241. package/dist/nop/models.d.ts +58 -0
  242. package/dist/nop/models.d.ts.map +1 -0
  243. package/dist/nop/models.js +50 -0
  244. package/dist/nop/models.js.map +1 -0
  245. package/dist/nop/nop-types.d.ts +136 -0
  246. package/dist/nop/nop-types.d.ts.map +1 -0
  247. package/dist/nop/nop-types.js +44 -0
  248. package/dist/nop/nop-types.js.map +1 -0
  249. package/dist/nop/registry.d.ts +3 -0
  250. package/dist/nop/registry.d.ts.map +1 -0
  251. package/dist/nop/registry.js +11 -0
  252. package/dist/nop/registry.js.map +1 -0
  253. package/dist/nwp/anchor-client.d.ts +109 -0
  254. package/dist/nwp/anchor-client.d.ts.map +1 -0
  255. package/dist/nwp/anchor-client.js +279 -0
  256. package/dist/nwp/anchor-client.js.map +1 -0
  257. package/dist/nwp/client.d.ts +28 -0
  258. package/dist/nwp/client.d.ts.map +1 -0
  259. package/dist/nwp/client.js +142 -0
  260. package/dist/nwp/client.js.map +1 -0
  261. package/dist/nwp/frames.d.ts +107 -0
  262. package/dist/nwp/frames.d.ts.map +1 -0
  263. package/dist/nwp/frames.js +198 -0
  264. package/dist/nwp/frames.js.map +1 -0
  265. package/dist/nwp/index.d.ts +6 -0
  266. package/dist/nwp/index.d.ts.map +1 -0
  267. package/{src/nwp/index.ts → dist/nwp/index.js} +3 -1
  268. package/dist/nwp/index.js.map +1 -0
  269. package/dist/nwp/manifest.d.ts +69 -0
  270. package/dist/nwp/manifest.d.ts.map +1 -0
  271. package/dist/nwp/manifest.js +4 -0
  272. package/dist/nwp/manifest.js.map +1 -0
  273. package/dist/nwp/registry.d.ts +3 -0
  274. package/dist/nwp/registry.d.ts.map +1 -0
  275. package/dist/nwp/registry.js +10 -0
  276. package/dist/nwp/registry.js.map +1 -0
  277. package/dist/setup.d.ts +10 -0
  278. package/dist/setup.d.ts.map +1 -0
  279. package/{src/setup.ts → dist/setup.js} +13 -16
  280. package/dist/setup.js.map +1 -0
  281. package/package.json +12 -1
  282. package/CONTRIBUTING.cn.md +0 -35
  283. package/CONTRIBUTING.md +0 -35
  284. package/nip-ca-server/Dockerfile +0 -27
  285. package/nip-ca-server/README.md +0 -45
  286. package/nip-ca-server/db/001_init.sql +0 -25
  287. package/nip-ca-server/docker-compose.yml +0 -29
  288. package/nip-ca-server/package.json +0 -23
  289. package/nip-ca-server/src/ca.ts +0 -155
  290. package/nip-ca-server/src/db.ts +0 -104
  291. package/nip-ca-server/src/index.ts +0 -157
  292. package/nip-ca-server/tsconfig.json +0 -13
  293. package/src/core/anchor-cache.ts +0 -129
  294. package/src/core/cache.ts +0 -93
  295. package/src/core/canonical-json.ts +0 -50
  296. package/src/core/codec.ts +0 -158
  297. package/src/core/codecs/ncp-codec.ts +0 -170
  298. package/src/core/crypto-provider.ts +0 -47
  299. package/src/core/exceptions.ts +0 -57
  300. package/src/core/frame-header.ts +0 -282
  301. package/src/core/frame-registry.ts +0 -91
  302. package/src/core/frames.ts +0 -184
  303. package/src/core/registry.ts +0 -28
  304. package/src/core/status-codes.ts +0 -47
  305. package/src/ncp/frames/anchor-frame.ts +0 -87
  306. package/src/ncp/frames/caps-frame.ts +0 -59
  307. package/src/ncp/frames/diff-frame.ts +0 -69
  308. package/src/ncp/frames/error-frame.ts +0 -26
  309. package/src/ncp/frames/hello-frame.ts +0 -50
  310. package/src/ncp/frames/stream-frame.ts +0 -35
  311. package/src/ncp/frames.ts +0 -251
  312. package/src/ncp/handshake.ts +0 -95
  313. package/src/ncp/ncp-error-codes.ts +0 -36
  314. package/src/ncp/ncp-patch-format.ts +0 -16
  315. package/src/ncp/preamble.ts +0 -79
  316. package/src/ncp/registry.ts +0 -15
  317. package/src/ncp/stream-manager.ts +0 -212
  318. package/src/ndp/dns-txt.ts +0 -86
  319. package/src/ndp/frames.ts +0 -124
  320. package/src/ndp/ndp-registry.ts +0 -116
  321. package/src/ndp/registry.ts +0 -12
  322. package/src/ndp/validator.ts +0 -64
  323. package/src/nip/acme/client.ts +0 -185
  324. package/src/nip/acme/jws.ts +0 -109
  325. package/src/nip/acme/messages.ts +0 -85
  326. package/src/nip/acme/server.ts +0 -480
  327. package/src/nip/acme/wire.ts +0 -24
  328. package/src/nip/assurance-level.ts +0 -40
  329. package/src/nip/cert-format.ts +0 -9
  330. package/src/nip/frames.ts +0 -138
  331. package/src/nip/identity.ts +0 -113
  332. package/src/nip/registry.ts +0 -12
  333. package/src/nip/verifier.ts +0 -122
  334. package/src/nip/x509/builder.ts +0 -91
  335. package/src/nip/x509/verifier.ts +0 -214
  336. package/src/nop/client.ts +0 -103
  337. package/src/nop/frames.ts +0 -181
  338. package/src/nop/models.ts +0 -79
  339. package/src/nop/nop-types.ts +0 -208
  340. package/src/nop/registry.ts +0 -13
  341. package/src/nwp/client.ts +0 -114
  342. package/src/nwp/frames.ts +0 -116
  343. package/src/nwp/registry.ts +0 -11
  344. package/tests/_rfc0002-keys.ts +0 -57
  345. package/tests/core/anchor-cache.test.ts +0 -242
  346. package/tests/core/codec.test.ts +0 -205
  347. package/tests/core/frame-registry.test.ts +0 -46
  348. package/tests/core.test.ts +0 -327
  349. package/tests/ncp/diff-binary-bitset.test.ts +0 -107
  350. package/tests/ncp/e2e-enc-reject.test.ts +0 -93
  351. package/tests/ncp/err-error-frame.test.ts +0 -152
  352. package/tests/ncp/frames.test.ts +0 -359
  353. package/tests/ncp/framing.test.ts +0 -233
  354. package/tests/ncp/hello-frame.test.ts +0 -122
  355. package/tests/ncp/inline-anchor.test.ts +0 -88
  356. package/tests/ncp/preamble.test.ts +0 -93
  357. package/tests/ncp/security.test.ts +0 -184
  358. package/tests/ncp/stream-window.test.ts +0 -167
  359. package/tests/ncp/stream.test.ts +0 -242
  360. package/tests/ncp/version-negotiation.test.ts +0 -123
  361. package/tests/ndp.test.ts +0 -377
  362. package/tests/nip-acme-agent01.test.ts +0 -192
  363. package/tests/nip-x509.test.ts +0 -280
  364. package/tests/nip.test.ts +0 -184
  365. package/tests/nop.test.ts +0 -344
  366. package/tests/nwp.test.ts +0 -237
  367. package/tsconfig.json +0 -20
  368. package/tsup.config.ts +0 -20
  369. package/vitest.config.ts +0 -10
package/src/nwp/frames.ts DELETED
@@ -1,116 +0,0 @@
1
- // Copyright 2026 INNO LOTUS PTY LTD
2
- // SPDX-License-Identifier: Apache-2.0
3
-
4
- import { EncodingTier, FrameType } from "../core/frames.js";
5
- import type { NpsFrame } from "../core/codec.js";
6
-
7
- // ── Filter DSL ────────────────────────────────────────────────────────────────
8
-
9
- export interface QueryOrderClause {
10
- field: string;
11
- dir: "asc" | "desc";
12
- }
13
-
14
- export interface VectorSearchOptions {
15
- vector: readonly number[];
16
- topK?: number;
17
- minScore?: number;
18
- vectorField?: string;
19
- }
20
-
21
- // ── QueryFrame ────────────────────────────────────────────────────────────────
22
-
23
- export class QueryFrame implements NpsFrame {
24
- readonly frameType = FrameType.QUERY;
25
- readonly preferredTier = EncodingTier.MSGPACK;
26
-
27
- constructor(
28
- public readonly anchorRef?: string,
29
- public readonly filter?: Record<string, unknown>,
30
- public readonly limit?: number,
31
- public readonly offset?: number,
32
- public readonly orderBy?: readonly QueryOrderClause[],
33
- public readonly fields?: readonly string[],
34
- public readonly vectorSearch?: VectorSearchOptions,
35
- public readonly depth?: number,
36
- ) {}
37
-
38
- toDict(): Record<string, unknown> {
39
- return {
40
- anchor_ref: this.anchorRef ?? null,
41
- filter: this.filter ?? null,
42
- limit: this.limit ?? null,
43
- offset: this.offset ?? null,
44
- order_by: this.orderBy ?? null,
45
- fields: this.fields ?? null,
46
- vector_search: this.vectorSearch ?? null,
47
- depth: this.depth ?? null,
48
- };
49
- }
50
-
51
- static fromDict(data: Record<string, unknown>): QueryFrame {
52
- return new QueryFrame(
53
- (data["anchor_ref"] as string | null) ?? undefined,
54
- (data["filter"] as Record<string, unknown> | null) ?? undefined,
55
- (data["limit"] as number | null) ?? undefined,
56
- (data["offset"] as number | null) ?? undefined,
57
- (data["order_by"] as QueryOrderClause[] | null) ?? undefined,
58
- (data["fields"] as string[] | null) ?? undefined,
59
- (data["vector_search"] as VectorSearchOptions | null) ?? undefined,
60
- (data["depth"] as number | null) ?? undefined,
61
- );
62
- }
63
- }
64
-
65
- // ── ActionFrame ───────────────────────────────────────────────────────────────
66
-
67
- export class ActionFrame implements NpsFrame {
68
- readonly frameType = FrameType.ACTION;
69
- readonly preferredTier = EncodingTier.MSGPACK;
70
-
71
- constructor(
72
- public readonly actionId: string,
73
- public readonly params?: Record<string, unknown>,
74
- public readonly async_?: boolean,
75
- public readonly idempotencyKey?: string,
76
- public readonly timeoutMs?: number,
77
- ) {}
78
-
79
- toDict(): Record<string, unknown> {
80
- return {
81
- action_id: this.actionId,
82
- params: this.params ?? null,
83
- async: this.async_ ?? false,
84
- idempotency_key: this.idempotencyKey ?? null,
85
- timeout_ms: this.timeoutMs ?? null,
86
- };
87
- }
88
-
89
- static fromDict(data: Record<string, unknown>): ActionFrame {
90
- return new ActionFrame(
91
- data["action_id"] as string,
92
- (data["params"] as Record<string, unknown> | null) ?? undefined,
93
- (data["async"] as boolean | null) ?? undefined,
94
- (data["idempotency_key"] as string | null) ?? undefined,
95
- (data["timeout_ms"] as number | null) ?? undefined,
96
- );
97
- }
98
- }
99
-
100
- // ── AsyncActionResponse ───────────────────────────────────────────────────────
101
-
102
- export interface AsyncActionResponse {
103
- taskId: string;
104
- status: string;
105
- pollUrl?: string | undefined;
106
- }
107
-
108
- export function asyncActionResponseFromDict(data: Record<string, unknown>): AsyncActionResponse {
109
- const r: AsyncActionResponse = {
110
- taskId: data["task_id"] as string,
111
- status: data["status"] as string,
112
- };
113
- const pollUrl = data["poll_url"] as string | null | undefined;
114
- if (pollUrl != null) r.pollUrl = pollUrl;
115
- return r;
116
- }
@@ -1,11 +0,0 @@
1
- // Copyright 2026 INNO LOTUS PTY LTD
2
- // SPDX-License-Identifier: Apache-2.0
3
-
4
- import { FrameRegistry } from "../core/registry.js";
5
- import { FrameType } from "../core/frames.js";
6
- import { ActionFrame, QueryFrame } from "./frames.js";
7
-
8
- export function registerNwpFrames(registry: FrameRegistry): void {
9
- registry.register(FrameType.QUERY, QueryFrame);
10
- registry.register(FrameType.ACTION, ActionFrame);
11
- }
@@ -1,57 +0,0 @@
1
- // Copyright 2026 INNO LOTUS PTY LTD
2
- // SPDX-License-Identifier: Apache-2.0
3
-
4
- // Shared key-generation helper for RFC-0002 tests. Underscore prefix keeps
5
- // vitest's `*.test.ts` discovery pattern from picking this up as a suite.
6
-
7
- import * as ed25519 from "@noble/ed25519";
8
- import { sha512 } from "@noble/hashes/sha512";
9
-
10
- ed25519.etc.sha512Sync = (...m) => sha512(ed25519.etc.concatBytes(...m));
11
-
12
- // PKCS8 / SPKI prefixes for Ed25519 are fixed-length and well-defined
13
- // (RFC 8410). Concatenating them with raw key bytes lets us shuttle a noble
14
- // keypair through Web Crypto's importKey for use with @peculiar/x509.
15
- const PKCS8_PREFIX = new Uint8Array([
16
- 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06,
17
- 0x03, 0x2b, 0x65, 0x70, 0x04, 0x22, 0x04, 0x20,
18
- ]);
19
- const SPKI_PREFIX = new Uint8Array([
20
- 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
21
- 0x70, 0x03, 0x21, 0x00,
22
- ]);
23
-
24
- export interface DualKeyPair {
25
- privRaw: Uint8Array; // 32 bytes — for noble signing
26
- pubRaw: Uint8Array; // 32 bytes — for IdentFrame.pub_key + JWK
27
- webCrypto: CryptoKeyPair; // for @peculiar/x509 signing / CSR generation
28
- }
29
-
30
- export async function generateDualKeyPair(): Promise<DualKeyPair> {
31
- const privRaw = ed25519.utils.randomPrivateKey();
32
- const pubRaw = ed25519.getPublicKey(privRaw);
33
-
34
- const pkcs8 = concat(PKCS8_PREFIX, privRaw);
35
- const spki = concat(SPKI_PREFIX, pubRaw);
36
-
37
- const subtle = globalThis.crypto.subtle;
38
- const privateKey = await subtle.importKey(
39
- "pkcs8", pkcs8.buffer as ArrayBuffer, { name: "Ed25519" }, true, ["sign"]);
40
- const publicKey = await subtle.importKey(
41
- "spki", spki.buffer as ArrayBuffer, { name: "Ed25519" }, true, ["verify"]);
42
-
43
- return { privRaw, pubRaw, webCrypto: { privateKey, publicKey } };
44
- }
45
-
46
- export function randomHexSerial(): string {
47
- const buf = new Uint8Array(20);
48
- globalThis.crypto.getRandomValues(buf);
49
- return Buffer.from(buf).toString("hex");
50
- }
51
-
52
- function concat(a: Uint8Array, b: Uint8Array): Uint8Array {
53
- const out = new Uint8Array(a.length + b.length);
54
- out.set(a, 0);
55
- out.set(b, a.length);
56
- return out;
57
- }
@@ -1,242 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // Copyright (c) 2026 LabAcacia / INNO LOTUS PTY LTD
3
- //
4
- // NCP Test Cases — AnchorCache
5
- // Covers: NCP-A-03, A-05, A-06, NCP-CA-01 to CA-05
6
- // Source: test/ncp_test_cases.md §3.1, §4
7
-
8
- import { describe, it, expect } from "vitest";
9
- import { NcpError } from "../../src/core/frame-header.js";
10
- import { AnchorCache } from "../../src/core/anchor-cache.js";
11
- import {
12
- computeAnchorId,
13
- type AnchorFrame,
14
- type FrameSchema,
15
- } from "../../src/ncp/frames/anchor-frame.js";
16
-
17
- // ---------------------------------------------------------------------------
18
- // Helpers
19
- // ---------------------------------------------------------------------------
20
-
21
- const schemaA: FrameSchema = {
22
- fields: [
23
- { name: "id", type: "uint64" },
24
- { name: "name", type: "string" },
25
- ],
26
- };
27
-
28
- const schemaB: FrameSchema = {
29
- fields: [
30
- { name: "id", type: "uint64" },
31
- { name: "price", type: "decimal" },
32
- ],
33
- };
34
-
35
- function makeAnchor(schema: FrameSchema, ttl?: number): AnchorFrame {
36
- return {
37
- frame: "0x01",
38
- anchor_id: computeAnchorId(schema),
39
- schema,
40
- ttl: ttl ?? 3600,
41
- };
42
- }
43
-
44
- // ===========================================================================
45
- // NCP-A-03: Anchor Poisoning
46
- // ===========================================================================
47
-
48
- describe("NCP-A-03: Anchor Poisoning", () => {
49
- // -----------------------------------------------------------------------
50
- // Spec: §7.2 — Same anchor_id with different schema → NCP-ANCHOR-ID-MISMATCH
51
- // -----------------------------------------------------------------------
52
- it("detects anchor poisoning (same ID, different schema)", () => {
53
- const cache = new AnchorCache();
54
- const anchor = makeAnchor(schemaA);
55
- cache.set(anchor);
56
-
57
- // Craft a poisoned frame: same anchor_id but different schema
58
- const poisoned: AnchorFrame = {
59
- frame: "0x01",
60
- anchor_id: anchor.anchor_id, // same ID
61
- schema: schemaB, // different schema!
62
- ttl: 3600,
63
- };
64
-
65
- expect(() => cache.set(poisoned)).toThrow(NcpError);
66
- try {
67
- cache.set(poisoned);
68
- } catch (e) {
69
- expect((e as NcpError).code).toBe("NCP-ANCHOR-ID-MISMATCH");
70
- }
71
- });
72
-
73
- it("allows idempotent set with same schema", () => {
74
- const cache = new AnchorCache();
75
- const anchor = makeAnchor(schemaA);
76
- cache.set(anchor);
77
- expect(() => cache.set(anchor)).not.toThrow(); // same schema — fine
78
- expect(cache.size).toBe(1);
79
- });
80
- });
81
-
82
- // ===========================================================================
83
- // NCP-A-05: Zero TTL
84
- // ===========================================================================
85
-
86
- describe("NCP-A-05: Zero TTL", () => {
87
- // -----------------------------------------------------------------------
88
- // Spec: §4.1 — ttl=0 means don't cache, use once
89
- // -----------------------------------------------------------------------
90
- it("does not cache frames with ttl=0", () => {
91
- const cache = new AnchorCache();
92
- const anchor = makeAnchor(schemaA, 0); // ttl=0
93
- cache.set(anchor);
94
-
95
- expect(cache.size).toBe(0);
96
- expect(cache.get(anchor.anchor_id)).toBeNull();
97
- });
98
- });
99
-
100
- // ===========================================================================
101
- // NCP-A-06: TTL Expiry
102
- // ===========================================================================
103
-
104
- describe("NCP-A-06: TTL Expiry", () => {
105
- // -----------------------------------------------------------------------
106
- // Spec: §5.3 — Expired anchors return not-found
107
- // -----------------------------------------------------------------------
108
- it("expires anchors after TTL", () => {
109
- let now = 1000;
110
- const cache = new AnchorCache({ getNow: () => now });
111
-
112
- const anchor = makeAnchor(schemaA, 1); // ttl=1 second
113
- cache.set(anchor);
114
-
115
- // Still valid
116
- expect(cache.get(anchor.anchor_id)).not.toBeNull();
117
-
118
- // Advance time past TTL
119
- now = 3000; // 2 seconds later
120
- expect(cache.get(anchor.anchor_id)).toBeNull();
121
- });
122
-
123
- it("getRequired throws NCP-ANCHOR-NOT-FOUND after expiry", () => {
124
- let now = 1000;
125
- const cache = new AnchorCache({ getNow: () => now });
126
-
127
- const anchor = makeAnchor(schemaA, 1);
128
- cache.set(anchor);
129
-
130
- now = 3000;
131
- expect(() => cache.getRequired(anchor.anchor_id)).toThrow(NcpError);
132
- try {
133
- cache.getRequired(anchor.anchor_id);
134
- } catch (e) {
135
- expect((e as NcpError).code).toBe("NCP-ANCHOR-NOT-FOUND");
136
- }
137
- });
138
- });
139
-
140
- // ===========================================================================
141
- // Group 4: Schema Caching
142
- // ===========================================================================
143
-
144
- describe("Group 4: Schema Caching", () => {
145
- // -----------------------------------------------------------------------
146
- // NCP-CA-01: Cache Hit
147
- // Spec: §5.3 — anchor_ref already in local cache
148
- // -----------------------------------------------------------------------
149
- it("NCP-CA-01: returns cached schema on hit", () => {
150
- const cache = new AnchorCache();
151
- const anchor = makeAnchor(schemaA);
152
- cache.set(anchor);
153
-
154
- const result = cache.get(anchor.anchor_id);
155
- expect(result).not.toBeNull();
156
- expect(result!.anchor_id).toBe(anchor.anchor_id);
157
- expect(result!.schema.fields).toHaveLength(2);
158
- });
159
-
160
- // -----------------------------------------------------------------------
161
- // NCP-CA-02: Cache Miss (Local)
162
- // Spec: §5.4 — Unknown anchor_ref → trigger fetch
163
- // -----------------------------------------------------------------------
164
- it("NCP-CA-02: returns null for unknown anchor_ref", () => {
165
- const cache = new AnchorCache();
166
- expect(cache.get("sha256:unknown")).toBeNull();
167
- });
168
-
169
- // -----------------------------------------------------------------------
170
- // NCP-CA-03: Cache Miss (Server)
171
- // Spec: §5.4.2 — Server returns NCP-ANCHOR-NOT-FOUND
172
- // -----------------------------------------------------------------------
173
- it("NCP-CA-03: getRequired throws NCP-ANCHOR-NOT-FOUND for unknown ref", () => {
174
- const cache = new AnchorCache();
175
- expect(() => cache.getRequired("sha256:fabricated")).toThrow(NcpError);
176
- try {
177
- cache.getRequired("sha256:fabricated");
178
- } catch (e) {
179
- expect((e as NcpError).code).toBe("NCP-ANCHOR-NOT-FOUND");
180
- }
181
- });
182
-
183
- // -----------------------------------------------------------------------
184
- // NCP-CA-04: LRU Eviction
185
- // Spec: §9 — Cache limit 1000, LRU eviction
186
- // -----------------------------------------------------------------------
187
- it("NCP-CA-04: evicts LRU entry when cache is full", () => {
188
- let now = 1000;
189
- const cache = new AnchorCache({ maxSize: 3, getNow: () => now });
190
-
191
- // Fill cache with 3 entries at different times
192
- const anchors = Array.from({ length: 3 }, (_, i) => {
193
- const schema: FrameSchema = {
194
- fields: [{ name: `field_${i}`, type: "string" }],
195
- };
196
- return makeAnchor(schema);
197
- });
198
- now = 1000; cache.set(anchors[0]!);
199
- now = 2000; cache.set(anchors[1]!);
200
- now = 3000; cache.set(anchors[2]!);
201
- expect(cache.size).toBe(3);
202
-
203
- // Access first anchor to make it most recently used
204
- now = 4000;
205
- cache.get(anchors[0]!.anchor_id);
206
-
207
- // Add 4th entry — should evict anchors[1] (lastAccessed=2000, the oldest)
208
- now = 5000;
209
- const newSchema: FrameSchema = {
210
- fields: [{ name: "field_new", type: "string" }],
211
- };
212
- const newAnchor = makeAnchor(newSchema);
213
- cache.set(newAnchor);
214
-
215
- expect(cache.size).toBe(3);
216
- expect(cache.get(anchors[0]!.anchor_id)).not.toBeNull(); // still here (accessed at 4000)
217
- expect(cache.get(anchors[1]!.anchor_id)).toBeNull(); // evicted (LRU at 2000)
218
- expect(cache.get(newAnchor.anchor_id)).not.toBeNull(); // newly added
219
- });
220
-
221
- // -----------------------------------------------------------------------
222
- // NCP-CA-05: Schema Update
223
- // Spec: §5.4.1 — Same name, different anchor_id can coexist
224
- // -----------------------------------------------------------------------
225
- it("NCP-CA-05: stores multiple schema versions by anchor_id", () => {
226
- const cache = new AnchorCache();
227
-
228
- // v1
229
- const anchorV1 = makeAnchor(schemaA);
230
- cache.set(anchorV1);
231
-
232
- // v2 (different schema → different anchor_id)
233
- const anchorV2 = makeAnchor(schemaB);
234
- cache.set(anchorV2);
235
-
236
- // Both should coexist
237
- expect(cache.get(anchorV1.anchor_id)).not.toBeNull();
238
- expect(cache.get(anchorV2.anchor_id)).not.toBeNull();
239
- expect(anchorV1.anchor_id).not.toBe(anchorV2.anchor_id);
240
- expect(cache.size).toBe(2);
241
- });
242
- });
@@ -1,205 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // Copyright (c) 2026 LabAcacia / INNO LOTUS PTY LTD
3
- //
4
- // NCP Test Cases — Codec dispatcher + MsgPack
5
- // Covers: NCP-F-04, F-09, NCP-E-02, E-04, E-05, E-06
6
- // Source: test/ncp_test_cases.md §1, §2
7
-
8
- import { describe, it, expect } from "vitest";
9
- import { EncodingTier, FrameType, NcpError } from "../../src/core/frame-header.js";
10
- import { encodeFrame, decodeFrame } from "../../src/core/codecs/ncp-codec.js";
11
- import { computeAnchorId, type FrameSchema } from "../../src/ncp/frames/anchor-frame.js";
12
-
13
- // ---------------------------------------------------------------------------
14
- // Helpers
15
- // ---------------------------------------------------------------------------
16
-
17
- const testSchema: FrameSchema = {
18
- fields: [
19
- { name: "id", type: "uint64" },
20
- { name: "name", type: "string" },
21
- ],
22
- };
23
-
24
- // ===========================================================================
25
- // NCP-F-04: EXT Flag Mismatch (High) — payload exceeds default max
26
- // ===========================================================================
27
-
28
- describe("NCP-F-04 / NCP-F-09: Payload size enforcement", () => {
29
- // -----------------------------------------------------------------------
30
- // NCP-F-09: Max Payload Enforced
31
- // Spec: §3.3 — Negotiated max_frame_payload
32
- // -----------------------------------------------------------------------
33
- it("NCP-F-09: rejects payload exceeding negotiated max", () => {
34
- // Encode a small frame, then decode with a tiny max
35
- const frame = encodeFrame(
36
- { frame: "0x01", anchor_id: "sha256:abc", schema: testSchema },
37
- { frameType: FrameType.Anchor },
38
- );
39
-
40
- expect(() => decodeFrame(frame, { maxFramePayload: 10 })).toThrow(NcpError);
41
- try {
42
- decodeFrame(frame, { maxFramePayload: 10 });
43
- } catch (e) {
44
- expect((e as NcpError).code).toBe("NCP-FRAME-PAYLOAD-TOO-LARGE");
45
- }
46
- });
47
-
48
- it("NCP-F-09: accepts payload within negotiated max", () => {
49
- const frame = encodeFrame(
50
- { frame: "0x01", data: "small" },
51
- { frameType: FrameType.Anchor },
52
- );
53
- expect(() => decodeFrame(frame, { maxFramePayload: 65535 })).not.toThrow();
54
- });
55
-
56
- // NCP-F-04: The codec auto-upgrades to extended header for large payloads
57
- it("NCP-F-04: auto-extends header for payload > 64KB", () => {
58
- const largeData = { frame: "0x03", data: "x".repeat(70_000) };
59
- const frame = encodeFrame(largeData, { frameType: FrameType.Stream });
60
-
61
- // Should have used extended header
62
- expect(frame[1]! & 0x80).toBe(0x80); // EXT bit set
63
-
64
- // Decode with large enough max
65
- const result = decodeFrame(frame, { maxFramePayload: 0xffffffff });
66
- expect((result.payload as { data: string }).data).toHaveLength(70_000);
67
- });
68
- });
69
-
70
- // ===========================================================================
71
- // NCP-E-02: Tier-2 MsgPack (Valid)
72
- // ===========================================================================
73
-
74
- describe("NCP-E-02 / E-04: Tier-2 MsgPack", () => {
75
- // -----------------------------------------------------------------------
76
- // NCP-E-02: Tier-2 MsgPack (Valid)
77
- // Spec: §3.2, §8 — Flags T0/T1 = 01
78
- // -----------------------------------------------------------------------
79
- it("NCP-E-02: round-trips frame via MsgPack encoding", () => {
80
- const anchor = {
81
- frame: "0x01",
82
- anchor_id: computeAnchorId(testSchema),
83
- schema: testSchema,
84
- ttl: 3600,
85
- };
86
-
87
- const encoded = encodeFrame(anchor, {
88
- frameType: FrameType.Anchor,
89
- tier: EncodingTier.MsgPack,
90
- });
91
- const result = decodeFrame(encoded);
92
-
93
- expect(result.header.tier).toBe(EncodingTier.MsgPack);
94
- const decoded = result.payload as typeof anchor;
95
- expect(decoded.frame).toBe("0x01");
96
- expect(decoded.ttl).toBe(3600);
97
- });
98
-
99
- // -----------------------------------------------------------------------
100
- // NCP-E-04: Tier-2 MsgPack (Malformed)
101
- // Spec: §3.2, §8 — Invalid MsgPack → NPS-CLIENT-BAD-FRAME
102
- // -----------------------------------------------------------------------
103
- it("NCP-E-04: rejects malformed MsgPack payload", () => {
104
- // Craft a frame with MsgPack tier flag but garbage payload
105
- const header = new Uint8Array([
106
- FrameType.Anchor, // frame type
107
- 0x01, // flags: Tier-2 MsgPack
108
- 0x00,
109
- 0x04, // payload length: 4
110
- ]);
111
- const garbage = new Uint8Array([0xff, 0xfe, 0xfd, 0xfc]);
112
- const frame = new Uint8Array(header.length + garbage.length);
113
- frame.set(header);
114
- frame.set(garbage, header.length);
115
-
116
- expect(() => decodeFrame(frame)).toThrow(NcpError);
117
- try {
118
- decodeFrame(frame);
119
- } catch (e) {
120
- expect((e as NcpError).code).toBe("NPS-CLIENT-BAD-FRAME");
121
- }
122
- });
123
- });
124
-
125
- // ===========================================================================
126
- // NCP-E-05: Reserved Tier
127
- // ===========================================================================
128
-
129
- describe("NCP-E-05: Reserved encoding tier", () => {
130
- // -----------------------------------------------------------------------
131
- // NCP-E-05: Reserved Tier (T3/T4)
132
- // Spec: §3.2, §8 — T0/T1 = 10 or 11 → NCP-ENCODING-UNSUPPORTED
133
- // -----------------------------------------------------------------------
134
- it("NCP-E-05: rejects reserved encoding tier 0x02", () => {
135
- // Craft header with tier bits = 10 (0x02)
136
- const header = new Uint8Array([
137
- FrameType.Anchor,
138
- 0x02, // flags: tier = 10 (reserved)
139
- 0x00,
140
- 0x02, // payload: 2 bytes
141
- ]);
142
- const payload = new Uint8Array([0x80, 0x00]); // dummy
143
- const frame = new Uint8Array(header.length + payload.length);
144
- frame.set(header);
145
- frame.set(payload, header.length);
146
-
147
- expect(() => decodeFrame(frame)).toThrow(NcpError);
148
- try {
149
- decodeFrame(frame);
150
- } catch (e) {
151
- expect((e as NcpError).code).toBe("NCP-ENCODING-UNSUPPORTED");
152
- }
153
- });
154
-
155
- it("NCP-E-05: rejects reserved encoding tier 0x03", () => {
156
- const header = new Uint8Array([
157
- FrameType.Anchor,
158
- 0x03, // flags: tier = 11 (reserved)
159
- 0x00,
160
- 0x02,
161
- ]);
162
- const payload = new Uint8Array([0x80, 0x00]);
163
- const frame = new Uint8Array(header.length + payload.length);
164
- frame.set(header);
165
- frame.set(payload, header.length);
166
-
167
- expect(() => decodeFrame(frame)).toThrow(NcpError);
168
- try {
169
- decodeFrame(frame);
170
- } catch (e) {
171
- expect((e as NcpError).code).toBe("NCP-ENCODING-UNSUPPORTED");
172
- }
173
- });
174
- });
175
-
176
- // ===========================================================================
177
- // NCP-E-06: Encoding Switch
178
- // ===========================================================================
179
-
180
- describe("NCP-E-06: Mid-session encoding switch", () => {
181
- // -----------------------------------------------------------------------
182
- // NCP-E-06: Encoding Switch
183
- // Spec: §8 — Different frames MAY use different tiers
184
- // -----------------------------------------------------------------------
185
- it("NCP-E-06: decodes JSON then MsgPack frames back-to-back", () => {
186
- const data = { frame: "0x04", anchor_ref: "sha256:abc", count: 0, data: [] };
187
-
188
- const jsonFrame = encodeFrame(data, {
189
- frameType: FrameType.Caps,
190
- tier: EncodingTier.Json,
191
- });
192
- const msgpackFrame = encodeFrame(data, {
193
- frameType: FrameType.Caps,
194
- tier: EncodingTier.MsgPack,
195
- });
196
-
197
- const result1 = decodeFrame(jsonFrame);
198
- expect(result1.header.tier).toBe(EncodingTier.Json);
199
- expect((result1.payload as { count: number }).count).toBe(0);
200
-
201
- const result2 = decodeFrame(msgpackFrame);
202
- expect(result2.header.tier).toBe(EncodingTier.MsgPack);
203
- expect((result2.payload as { count: number }).count).toBe(0);
204
- });
205
- });
@@ -1,46 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // Copyright (c) 2026 LabAcacia / INNO LOTUS PTY LTD
3
- //
4
- // NCP Test Cases — NCP-F-08: Unknown Frame Type
5
- // Source: test/ncp_test_cases.md §1
6
-
7
- import { describe, it, expect } from "vitest";
8
- import { FrameType, NcpError } from "../../src/core/frame-header.js";
9
- import { FrameRegistry } from "../../src/core/frame-registry.js";
10
-
11
- describe("NCP-F-08: Unknown Frame Type", () => {
12
- const registry = FrameRegistry.createDefault();
13
-
14
- // -----------------------------------------------------------------------
15
- // NCP-F-08: Unknown Frame Type
16
- // Spec: §2.3 — Frame type routing table
17
- // -----------------------------------------------------------------------
18
- it("rejects unregistered frame type 0x88", () => {
19
- expect(() => registry.resolve(0x88)).toThrow(NcpError);
20
- try {
21
- registry.resolve(0x88);
22
- expect.unreachable("should have thrown");
23
- } catch (e) {
24
- expect((e as NcpError).code).toBe("NCP-FRAME-UNKNOWN-TYPE");
25
- }
26
- });
27
-
28
- it("resolves registered NCP frame types", () => {
29
- expect(registry.resolve(FrameType.Anchor).name).toBe("AnchorFrame");
30
- expect(registry.resolve(FrameType.Diff).name).toBe("DiffFrame");
31
- expect(registry.resolve(FrameType.Stream).name).toBe("StreamFrame");
32
- expect(registry.resolve(FrameType.Caps).name).toBe("CapsFrame");
33
- expect(registry.resolve(FrameType.Hello).name).toBe("HelloFrame");
34
- expect(registry.resolve(FrameType.Error).name).toBe("ErrorFrame");
35
- });
36
-
37
- it("resolves protocol for frame types", () => {
38
- expect(registry.resolve(FrameType.Anchor).protocol).toBe("ncp");
39
- expect(registry.resolve(FrameType.Error).protocol).toBe("system");
40
- });
41
-
42
- it("has() returns false for unregistered types", () => {
43
- expect(registry.has(0x88)).toBe(false);
44
- expect(registry.has(FrameType.Anchor)).toBe(true);
45
- });
46
- });