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

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 (365) hide show
  1. package/CHANGELOG.cn.md +115 -0
  2. package/CHANGELOG.md +124 -0
  3. package/README.cn.md +3 -1
  4. package/README.md +3 -1
  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 +81 -0
  54. package/dist/core/frames.d.ts.map +1 -0
  55. package/dist/core/frames.js +154 -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 +22 -0
  258. package/dist/nwp/client.d.ts.map +1 -0
  259. package/dist/nwp/client.js +101 -0
  260. package/dist/nwp/client.js.map +1 -0
  261. package/dist/nwp/frames.d.ts +46 -0
  262. package/dist/nwp/frames.d.ts.map +1 -0
  263. package/dist/nwp/frames.js +81 -0
  264. package/dist/nwp/frames.js.map +1 -0
  265. package/dist/nwp/index.d.ts +5 -0
  266. package/dist/nwp/index.d.ts.map +1 -0
  267. package/{src/nwp/index.ts → dist/nwp/index.js} +2 -1
  268. package/dist/nwp/index.js.map +1 -0
  269. package/dist/nwp/registry.d.ts +3 -0
  270. package/dist/nwp/registry.d.ts.map +1 -0
  271. package/dist/nwp/registry.js +9 -0
  272. package/dist/nwp/registry.js.map +1 -0
  273. package/dist/setup.d.ts +10 -0
  274. package/dist/setup.d.ts.map +1 -0
  275. package/{src/setup.ts → dist/setup.js} +13 -16
  276. package/dist/setup.js.map +1 -0
  277. package/package.json +12 -1
  278. package/CONTRIBUTING.cn.md +0 -35
  279. package/CONTRIBUTING.md +0 -35
  280. package/nip-ca-server/Dockerfile +0 -27
  281. package/nip-ca-server/README.md +0 -45
  282. package/nip-ca-server/db/001_init.sql +0 -25
  283. package/nip-ca-server/docker-compose.yml +0 -29
  284. package/nip-ca-server/package.json +0 -23
  285. package/nip-ca-server/src/ca.ts +0 -155
  286. package/nip-ca-server/src/db.ts +0 -104
  287. package/nip-ca-server/src/index.ts +0 -157
  288. package/nip-ca-server/tsconfig.json +0 -13
  289. package/src/core/anchor-cache.ts +0 -129
  290. package/src/core/cache.ts +0 -93
  291. package/src/core/canonical-json.ts +0 -50
  292. package/src/core/codec.ts +0 -158
  293. package/src/core/codecs/ncp-codec.ts +0 -170
  294. package/src/core/crypto-provider.ts +0 -47
  295. package/src/core/exceptions.ts +0 -57
  296. package/src/core/frame-header.ts +0 -282
  297. package/src/core/frame-registry.ts +0 -91
  298. package/src/core/frames.ts +0 -184
  299. package/src/core/registry.ts +0 -28
  300. package/src/core/status-codes.ts +0 -47
  301. package/src/ncp/frames/anchor-frame.ts +0 -87
  302. package/src/ncp/frames/caps-frame.ts +0 -59
  303. package/src/ncp/frames/diff-frame.ts +0 -69
  304. package/src/ncp/frames/error-frame.ts +0 -26
  305. package/src/ncp/frames/hello-frame.ts +0 -50
  306. package/src/ncp/frames/stream-frame.ts +0 -35
  307. package/src/ncp/frames.ts +0 -251
  308. package/src/ncp/handshake.ts +0 -95
  309. package/src/ncp/ncp-error-codes.ts +0 -36
  310. package/src/ncp/ncp-patch-format.ts +0 -16
  311. package/src/ncp/preamble.ts +0 -79
  312. package/src/ncp/registry.ts +0 -15
  313. package/src/ncp/stream-manager.ts +0 -212
  314. package/src/ndp/dns-txt.ts +0 -86
  315. package/src/ndp/frames.ts +0 -124
  316. package/src/ndp/ndp-registry.ts +0 -116
  317. package/src/ndp/registry.ts +0 -12
  318. package/src/ndp/validator.ts +0 -64
  319. package/src/nip/acme/client.ts +0 -185
  320. package/src/nip/acme/jws.ts +0 -109
  321. package/src/nip/acme/messages.ts +0 -85
  322. package/src/nip/acme/server.ts +0 -480
  323. package/src/nip/acme/wire.ts +0 -24
  324. package/src/nip/assurance-level.ts +0 -40
  325. package/src/nip/cert-format.ts +0 -9
  326. package/src/nip/frames.ts +0 -138
  327. package/src/nip/identity.ts +0 -113
  328. package/src/nip/registry.ts +0 -12
  329. package/src/nip/verifier.ts +0 -122
  330. package/src/nip/x509/builder.ts +0 -91
  331. package/src/nip/x509/verifier.ts +0 -214
  332. package/src/nop/client.ts +0 -103
  333. package/src/nop/frames.ts +0 -181
  334. package/src/nop/models.ts +0 -79
  335. package/src/nop/nop-types.ts +0 -208
  336. package/src/nop/registry.ts +0 -13
  337. package/src/nwp/client.ts +0 -114
  338. package/src/nwp/frames.ts +0 -116
  339. package/src/nwp/registry.ts +0 -11
  340. package/tests/_rfc0002-keys.ts +0 -57
  341. package/tests/core/anchor-cache.test.ts +0 -242
  342. package/tests/core/codec.test.ts +0 -205
  343. package/tests/core/frame-registry.test.ts +0 -46
  344. package/tests/core.test.ts +0 -327
  345. package/tests/ncp/diff-binary-bitset.test.ts +0 -107
  346. package/tests/ncp/e2e-enc-reject.test.ts +0 -93
  347. package/tests/ncp/err-error-frame.test.ts +0 -152
  348. package/tests/ncp/frames.test.ts +0 -359
  349. package/tests/ncp/framing.test.ts +0 -233
  350. package/tests/ncp/hello-frame.test.ts +0 -122
  351. package/tests/ncp/inline-anchor.test.ts +0 -88
  352. package/tests/ncp/preamble.test.ts +0 -93
  353. package/tests/ncp/security.test.ts +0 -184
  354. package/tests/ncp/stream-window.test.ts +0 -167
  355. package/tests/ncp/stream.test.ts +0 -242
  356. package/tests/ncp/version-negotiation.test.ts +0 -123
  357. package/tests/ndp.test.ts +0 -377
  358. package/tests/nip-acme-agent01.test.ts +0 -192
  359. package/tests/nip-x509.test.ts +0 -280
  360. package/tests/nip.test.ts +0 -184
  361. package/tests/nop.test.ts +0 -344
  362. package/tests/nwp.test.ts +0 -237
  363. package/tsconfig.json +0 -20
  364. package/tsup.config.ts +0 -20
  365. package/vitest.config.ts +0 -10
package/CHANGELOG.cn.md CHANGED
@@ -8,6 +8,120 @@
8
8
 
9
9
  ---
10
10
 
11
+ ## [1.0.0-alpha.7] —— 2026-05-17
12
+
13
+ ### 新增
14
+
15
+ - **`nip/reputation-client.ts` — `ReputationLogClient`(NPS-RFC-0004 Phase 2)**:基于 fetch 的声誉日志 operator 完整客户端。`submitEntry`、`queryEntries`、`getSth`、`getProof`、`getGossipSth`。`verifyInclusion` 使用 `@noble/hashes/sha256` 在本地执行 RFC 9162 §2.1.3.2 Merkle audit-path 验证。`signEntry` / `verifyEntry` 使用 `@noble/ed25519` 签名验证条目。Wire 类型:`ReputationLogEntry`、`SignedTreeHead`、`InclusionProof`、`ObservationWindow`。`AnchorTopologyError` 携带 `nwpErrorCode` + `npsStatus`。30 条回归测试。从 `@labacacia/nps-sdk/nip` 重新导出。
16
+
17
+ - **`nwp/anchor-client.ts` — `AnchorNodeClient`(NPS-CR-0002)**:基于 fetch 的 Anchor Node 拓扑查询客户端。`getSnapshot`(topology.snapshot)和 `subscribe` async generator(topology.stream NDJSON)。判别联合类型 `TopologyEvent`,包含 `member_joined`、`member_left`、`member_updated`、`anchor_state`、`resync_required` 五种 kind。`AnchorTopologyError` 处理协议错误。24 条回归测试。
18
+
19
+ ### 跟随套件
20
+
21
+ 本次跟随 NPS 套件 `v1.0.0-alpha.7`。
22
+
23
+ ---
24
+
25
+ ## [1.0.0-alpha.6] —— 2026-05-14
26
+
27
+ ### 变更
28
+
29
+ - **`nip/x509/oids.ts` — IANA PEN 65715(Breaking,CR-0004)**:`LAB_ACACIA_PEN_ARC` 从 `"1.3.6.1.4.1.99999"` 更新为 `"1.3.6.1.4.1.65715"`。在临时弧下签发的证书必须吊销并重新签发。
30
+
31
+ - **`nwp/index.ts` — 移除 `NwpErrorCodes` 重导出(Breaking)**:从桶文件中移除了 `export * as NwpErrorCodes from "./error-codes.js"`。如需使用,请直接从 `@labacacia/nps-sdk/nwp/error-codes` 导入。
32
+
33
+ - **版本升级至 `1.0.0-alpha.6`** —— 与 NPS 套件 alpha.6 版本同步。
34
+
35
+ ---
36
+
37
+ ## [1.0.0-alpha.5] —— 2026-05-01
38
+
39
+ ### 新增
40
+
41
+ - **NWP 错误码常量** —— 新增 `NwpErrorCodes` 命名空间,从 `@labacacia/nps-sdk/nwp` 导出,包含全部 30 个 NWP wire 错误码(auth、query、action、task、subscribe、infrastructure、manifest、topology、reserved-type)。此前版本均未提供。
42
+ - **`NpsStatusCodes.NPS_SERVER_UNSUPPORTED`** —— 在 `src/core/status-codes.ts` 新增状态码 `"NPS-SERVER-UNSUPPORTED"`(HTTP 501),符合 spec/status-codes.md alpha.5 更新。
43
+ - **`NDP.resolveWithDns` —— DNS TXT 回退解析** —— 新增 `InMemoryNdpRegistry.resolveWithDns(target, resolver?)`,当内存注册表无匹配时回退查询 `_nps-node.{host}` TXT 记录(NPS-4 §5)。新增 `DnsTxtLookup` 接口 + `SystemDnsTxtLookup`(Node.js `dns.promises`);`parseNpsTxtRecord` + `extractHostFromTarget` 从 `@labacacia/nps-sdk/ndp` 导出。测试数:284 → 294。
44
+
45
+ ### 变更
46
+
47
+ - **`AssuranceLevel.fromWire("")` 返回 `Anonymous`** —— `if (wire == null)` 改为 `if (!wire)`,使 `""` 返回 `Anonymous` 而非 `Unknown`(spec §5.1.1 向后兼容修复)。
48
+ - **版本升至 `1.0.0-alpha.5`** —— 与 NPS 套件 alpha.5 同步。
49
+
50
+ ### 修复
51
+
52
+ - **`REPUTATION_GOSSIP_FORK` / `REPUTATION_GOSSIP_SIG_INVALID`** —— 向 `src/nip/error-codes.ts` 新增两个 NIP 声誉 gossip 错误码(RFC-0004 Phase 3)。
53
+
54
+ ---
55
+
56
+ ## [1.0.0-alpha.4] —— 2026-04-30
57
+
58
+ ### 新增
59
+
60
+ - **NPS-RFC-0001 Phase 2 —— NCP 连接前导(TypeScript helper 跟进)。**
61
+ `src/ncp/preamble.ts` 暴露 `writePreamble(stream)` /
62
+ `readPreamble(stream)`,往返字面量 `b"NPS/1.0\n"` 哨兵;
63
+ `tests/ncp/preamble.test.ts` 覆盖。让 TypeScript SDK 与 .NET /
64
+ Python / Go / Java 在 alpha.4 的 preamble helper 持平。
65
+ - **NPS-RFC-0002 Phase A/B —— X.509 NID 证书 + ACME `agent-01`
66
+ (TypeScript 端口)。** 新增 `src/nip/` 子模块:
67
+ - `nip/x509/` —— X.509 NID 证书 builder + verifier
68
+ (`x509.Builder`、`x509.Verifier`)。
69
+ - `nip/acme/` —— ACME `agent-01` 客户端 + 服务端参考实现
70
+ (`AcmeServer`、`AcmeClient`);按 NPS-RFC-0002 Phase B 的 JWS
71
+ 签名 wire 包络。
72
+ - `nip/assurance-level.ts` —— Agent 身份保证等级
73
+ (`anonymous` / `attested` / `verified`),承接 NPS-RFC-0003。
74
+ - `nip/cert-format.ts` —— IdentFrame `cert_format` 判别器
75
+ (`v1` Ed25519 vs. `x509`)。
76
+ - `nip/error-codes.ts` —— NIP 错误码命名空间。
77
+ - `nip/verifier.ts` —— dual-trust IdentFrame 验证器(v1 + X.509)。
78
+ - 20 个新测试覆盖 preamble 往返、X.509 签发 + 解析、dual-trust 验证、
79
+ ACME agent-01 全流程。总数:284 tests 全绿(alpha.3 时 264)。
80
+
81
+ ### 变更
82
+
83
+ - 分发版本升至 `1.0.0-alpha.4`。
84
+ - `src/nip/frames.ts` —— IdentFrame wire 形状扩展,可携带可选的
85
+ `cert_format` 判别器 + `x509_chain` 字段,与 v1 Ed25519 字段并存。
86
+ alpha.3 写出的 v1 IdentFrame 仍可被 alpha.4 验签。
87
+
88
+ ### npm 发布说明
89
+
90
+ - 本仓库 / tag 是 `@labacacia/nps-sdk` `1.0.0-alpha.4` 的权威参考。
91
+ 延续 alpha.3 的情况,npm publish 可能需要带 2FA-bypass 的 granular
92
+ access token —— 如果 npm registry 上的版本暂时落后于本仓库 tag,
93
+ 以 tag 为准;下一次 registry cut 后 `npm install` 即可解析到本
94
+ commit。
95
+
96
+ ### 套件级 alpha.4 要点
97
+
98
+ - **NPS-RFC-0002 X.509 + ACME** —— 完整跨 SDK 端口波(.NET / Java /
99
+ Python / TypeScript / Go / Rust)。
100
+ - **NPS-CR-0002 —— Anchor Node topology 查询** —— `topology.snapshot`
101
+ / `topology.stream`(.NET 参考 + L2 conformance)。TypeScript 消费
102
+ 侧 helper 后续版本跟进。
103
+ - **`nps-registry` SQLite 实仓** + **`nps-ledger` Phase 2**
104
+ (RFC 9162 Merkle + STH + inclusion proof)已在 daemon 仓库交付。
105
+
106
+ ---
107
+
108
+ ## [1.0.0-alpha.3] —— 2026-04-25
109
+
110
+ ### Changed
111
+
112
+ - 版本升级至 `1.0.0-alpha.3`,与 NPS `v1.0.0-alpha.3` 套件同步。本次 TypeScript SDK 无功能变更。
113
+ - 264 tests, ≥98% 覆盖率仍全绿。
114
+
115
+ ### 套件级 alpha.3 要点(各语言 helper 在 alpha.4 跟进)
116
+
117
+ - **NPS-RFC-0001 —— NCP 连接前导**(Accepted)。原生模式连接现以字面量 `b"NPS/1.0\n"`(8 字节)开头。.NET SDK 已落地参考实现;TypeScript helper 在 alpha.4 跟进。
118
+ - **NPS-RFC-0003 —— Agent 身份保证等级**(Accepted)。NIP IdentFrame 与 NWM 新增三态 `assurance_level`(`anonymous`/`attested`/`verified`)。.NET 参考类型已落地;TypeScript 同步在 alpha.4。
119
+ - **NPS-RFC-0004 —— NID 声誉日志(CT 风格)**(Accepted)。append-only Merkle 日志条目结构发布;.NET 参考签名器已落地(并以 `nps-ledger` daemon Phase 1 形态发布)。TypeScript helper 在 alpha.4 跟进。
120
+ - **NPS-CR-0001 —— Anchor / Bridge 节点拆分。** 旧的 "Gateway Node" 角色更名为 **Anchor Node**;"NPS↔外部协议翻译" 单独成为 **Bridge Node** 类型。AnnounceFrame 新增 `node_kind` / `cluster_anchor` / `bridge_protocols`。源代码层面变更落在 `spec/` + .NET 参考实现。
121
+ - **6 个 NPS 常驻 daemon。** NPS-Dev 新建 `daemons/` 目录,定义 `npsd` / `nps-runner` / `nps-gateway` / `nps-registry` / `nps-cloud-ca` / `nps-ledger`;其中 `npsd` 提供 L1 功能性参考实现,其余为 Phase 1 骨架。
122
+
123
+ ---
124
+
11
125
  ## [1.0.0-alpha.2] —— 2026-04-19
12
126
 
13
127
  ### Fixed
@@ -35,5 +149,6 @@
35
149
 
36
150
  作为 NPS 套件 `v1.0.0-alpha.1` 的一部分首次公开 alpha。
37
151
 
152
+ [1.0.0-alpha.7]: https://github.com/labacacia/NPS-sdk-ts/releases/tag/v1.0.0-alpha.7
38
153
  [1.0.0-alpha.2]: https://github.com/LabAcacia/nps/releases/tag/v1.0.0-alpha.2
39
154
  [1.0.0-alpha.1]: https://github.com/LabAcacia/nps/releases/tag/v1.0.0-alpha.1
package/CHANGELOG.md CHANGED
@@ -8,6 +8,129 @@ Until NPS reaches v1.0 stable, every repository in the suite is synchronized to
8
8
 
9
9
  ---
10
10
 
11
+ ## [1.0.0-alpha.7] — 2026-05-17
12
+
13
+ ### Added
14
+
15
+ - **`nip/reputation-client.ts` — `ReputationLogClient` (NPS-RFC-0004 Phase 2)**: Full fetch-based client for the reputation-log operator API. `submitEntry`, `queryEntries`, `getSth`, `getProof`, `getGossipSth`. `verifyInclusion` performs RFC 9162 §2.1.3.2 Merkle audit-path verification locally using `@noble/hashes/sha256`. `signEntry` / `verifyEntry` sign and verify entries with `@noble/ed25519`. Wire types: `ReputationLogEntry`, `SignedTreeHead`, `InclusionProof`, `ObservationWindow`. `AnchorTopologyError` carries `nwpErrorCode` + `npsStatus`. 30 regression tests. Re-exported from `@labacacia/nps-sdk/nip`.
16
+
17
+ - **`nwp/anchor-client.ts` — `AnchorNodeClient` (NPS-CR-0002)**: Fetch-based client for Anchor Node topology queries. `getSnapshot` (topology.snapshot) and `subscribe` async generator (topology.stream NDJSON). Discriminated-union `TopologyEvent` with kinds: `member_joined`, `member_left`, `member_updated`, `anchor_state`, `resync_required`. `AnchorTopologyError` for protocol errors. 24 regression tests.
18
+
19
+ ### Tracking the suite
20
+
21
+ This release tracks NPS suite `v1.0.0-alpha.7`.
22
+
23
+ ---
24
+
25
+ ## [1.0.0-alpha.6] — 2026-05-14
26
+
27
+ ### Changed
28
+
29
+ - **`nip/x509/oids.ts` — IANA PEN 65715 (Breaking, CR-0004)**: `LAB_ACACIA_PEN_ARC` updated from `"1.3.6.1.4.1.99999"` to `"1.3.6.1.4.1.65715"`. Certificates issued under the provisional arc must be revoked and re-issued.
30
+
31
+ - **`nwp/index.ts` — `NwpErrorCodes` re-export removed (Breaking)**: `export * as NwpErrorCodes from "./error-codes.js"` removed from the barrel. Import directly from `@labacacia/nps-sdk/nwp/error-codes` if needed.
32
+
33
+ - **Version bump to `1.0.0-alpha.6`** — synchronized with NPS suite alpha.6 release.
34
+
35
+ ---
36
+
37
+ ## [1.0.0-alpha.5] — 2026-05-01
38
+
39
+ ### Added
40
+
41
+ - **NWP error code constants** — new `NwpErrorCodes` namespace exported from `@labacacia/nps-sdk/nwp` with all 30 NWP wire error codes (auth, query, action, task, subscribe, infrastructure, manifest, topology, reserved-type). Missing from previous releases.
42
+ - **`NpsStatusCodes.NPS_SERVER_UNSUPPORTED`** — new status code `"NPS-SERVER-UNSUPPORTED"` (HTTP 501) in `src/core/status-codes.ts`, per spec/status-codes.md alpha.5 update.
43
+ - **`NDP.resolveWithDns` — DNS TXT fallback resolution** — new `InMemoryNdpRegistry.resolveWithDns(target, resolver?)` falls back to `_nps-node.{host}` TXT record lookup (NPS-4 §5) when no in-memory entry matches. New `DnsTxtLookup` interface + `SystemDnsTxtLookup` (Node.js `dns.promises`); `parseNpsTxtRecord` + `extractHostFromTarget` helpers exported from `@labacacia/nps-sdk/ndp`. Tests: 284 → 294.
44
+
45
+ ### Changed
46
+
47
+ - **`AssuranceLevel.fromWire("")` returns `Anonymous`** — `if (wire == null)` changed to `if (!wire)` so `""` returns `Anonymous` instead of `Unknown` (spec §5.1.1 backward-compat fix).
48
+ - **Version bump to `1.0.0-alpha.5`** — synchronized with NPS suite alpha.5 release.
49
+
50
+ ### Fixed
51
+
52
+ - **`REPUTATION_GOSSIP_FORK` / `REPUTATION_GOSSIP_SIG_INVALID`** — two new NIP reputation gossip error codes added to `src/nip/error-codes.ts` (RFC-0004 Phase 3).
53
+
54
+ ---
55
+
56
+ ## [1.0.0-alpha.4] — 2026-04-30
57
+
58
+ ### Added
59
+
60
+ - **NPS-RFC-0001 Phase 2 — NCP connection preamble (TypeScript helper
61
+ parity).** `src/ncp/preamble.ts` exposes `writePreamble(stream)` and
62
+ `readPreamble(stream)` round-tripping the literal `b"NPS/1.0\n"`
63
+ sentinel; matched by `tests/ncp/preamble.test.ts`. Brings TypeScript
64
+ in line with the .NET / Python / Go / Java preamble helpers shipped
65
+ at alpha.4.
66
+ - **NPS-RFC-0002 Phase A/B — X.509 NID certificates + ACME `agent-01`
67
+ (TypeScript port).** New surface under `src/nip/`:
68
+ - `nip/x509/` — X.509 NID certificate builder + verifier
69
+ (`x509.Builder`, `x509.Verifier`).
70
+ - `nip/acme/` — ACME `agent-01` client + server reference
71
+ (`AcmeServer`, `AcmeClient`); JWS-signed wire envelope per
72
+ NPS-RFC-0002 Phase B.
73
+ - `nip/assurance-level.ts` — agent identity assurance levels
74
+ (`anonymous` / `attested` / `verified`) per NPS-RFC-0003.
75
+ - `nip/cert-format.ts` — IdentFrame `cert_format` discriminator
76
+ (`v1` Ed25519 vs. `x509`).
77
+ - `nip/error-codes.ts` — NIP error code namespace strings.
78
+ - `nip/verifier.ts` — dual-trust IdentFrame verifier (v1 + X.509).
79
+ - 20 new tests covering preamble round-trip, X.509 issuance + parsing,
80
+ dual-trust verification, and ACME agent-01 round-trip. Total: 284
81
+ tests green (was 264 at alpha.3).
82
+
83
+ ### Changed
84
+
85
+ - Distribution version bumped to `1.0.0-alpha.4`.
86
+ - `src/nip/frames.ts` — IdentFrame wire shape extended with optional
87
+ `cert_format` discriminator + `x509_chain` field alongside the
88
+ existing v1 Ed25519 fields. v1 IdentFrames written by alpha.3
89
+ consumers continue to verify unchanged.
90
+
91
+ ### Note: npm publish status
92
+
93
+ - This repo / tag is the canonical `1.0.0-alpha.4` reference for
94
+ `@labacacia/nps-sdk`. As at the alpha.3 ship cycle, npm publish
95
+ may require a granular access token with 2FA-bypass enabled — if
96
+ the registry version lags this repo's tag, the tag is the
97
+ authoritative artifact and `npm install` against the next
98
+ registry cut will resolve to this commit.
99
+
100
+ ### Suite-wide highlights at alpha.4
101
+
102
+ - **NPS-RFC-0002 X.509 + ACME** — full cross-SDK port wave (.NET /
103
+ Java / Python / TypeScript / Go / Rust). Servers can now issue
104
+ dual-trust IdentFrames (v1 Ed25519 + X.509 leaf cert chained to a
105
+ self-signed root) and self-onboard NIDs over ACME's `agent-01`
106
+ challenge type.
107
+ - **NPS-CR-0002 — Anchor Node topology queries** — `topology.snapshot`
108
+ / `topology.stream` query types (.NET reference + L2 conformance
109
+ suite). TypeScript consumer-side helpers planned for a later
110
+ release.
111
+ - **`nps-registry` SQLite-backed real registry** + **`nps-ledger`
112
+ Phase 2** (RFC 9162 Merkle + STH + inclusion proofs) shipped in the
113
+ daemon repos.
114
+
115
+ ---
116
+
117
+ ## [1.0.0-alpha.3] — 2026-04-25
118
+
119
+ ### Changed
120
+
121
+ - Version bump to `1.0.0-alpha.3` for suite-wide synchronization with the NPS `v1.0.0-alpha.3` release. No functional changes in the TypeScript SDK at this milestone.
122
+ - 264 tests, ≥98% coverage still green.
123
+
124
+ ### Suite-wide highlights at alpha.3 (per-language helpers planned for alpha.4)
125
+
126
+ - **NPS-RFC-0001 — NCP connection preamble** (Accepted). Native-mode connections now begin with the literal `b"NPS/1.0\n"` (8 bytes). Reference helper landed in the .NET SDK; TypeScript helper deferred to alpha.4.
127
+ - **NPS-RFC-0003 — Agent identity assurance levels** (Accepted). NIP IdentFrame and NWM gain a tri-state `assurance_level` (`anonymous`/`attested`/`verified`). Reference types landed in .NET; TypeScript parity deferred to alpha.4.
128
+ - **NPS-RFC-0004 — NID reputation log (CT-style)** (Accepted). Append-only Merkle log entry shape published; reference signer landed in .NET (and shipped as the `nps-ledger` daemon Phase 1). TypeScript helpers deferred to alpha.4.
129
+ - **NPS-CR-0001 — Anchor / Bridge node split.** The legacy "Gateway Node" role is renamed to **Anchor Node**; the "translate NPS↔external protocol" role is now its own **Bridge Node** type. AnnounceFrame gained `node_kind` / `cluster_anchor` / `bridge_protocols`. Source-of-truth changes are in `spec/` + the .NET reference implementation.
130
+ - **6 NPS resident daemons.** New `daemons/` tree in NPS-Dev defines `npsd` / `nps-runner` / `nps-gateway` / `nps-registry` / `nps-cloud-ca` / `nps-ledger`; `npsd` ships an L1-functional reference and the rest ship as Phase 1 skeletons.
131
+
132
+ ---
133
+
11
134
  ## [1.0.0-alpha.2] — 2026-04-19
12
135
 
13
136
  ### Fixed
@@ -35,5 +158,6 @@ Until NPS reaches v1.0 stable, every repository in the suite is synchronized to
35
158
 
36
159
  First public alpha as part of the NPS suite `v1.0.0-alpha.1` release.
37
160
 
161
+ [1.0.0-alpha.7]: https://github.com/labacacia/NPS-sdk-ts/releases/tag/v1.0.0-alpha.7
38
162
  [1.0.0-alpha.2]: https://github.com/LabAcacia/nps/releases/tag/v1.0.0-alpha.2
39
163
  [1.0.0-alpha.1]: https://github.com/LabAcacia/nps/releases/tag/v1.0.0-alpha.1
package/README.cn.md CHANGED
@@ -9,6 +9,8 @@
9
9
 
10
10
  **v1.0.0-alpha.6 — RFC-0002 跨 SDK 端口波(第三棒)** · 5 个协议 · 271 个测试 · 覆盖率 ≥ 98%
11
11
 
12
+ > npm registry 说明:`@labacacia/nps-sdk@1.0.0-alpha.6` 已 deprecated,因为发布到 npm 的 tarball 缺少 `dist/`。当前 `alpha` dist-tag 临时指向 `1.0.0-alpha.5`;需要 alpha.6 源码时请使用 GitHub `v1.0.0-alpha.6` tag,等待下一个 npm 预发布。
13
+
12
14
  | 协议 | 类 | 状态 |
13
15
  |------|----|------|
14
16
  | NCP — Neural Communication Protocol | 帧、编解码器 | ✅ |
@@ -26,7 +28,7 @@
26
28
  ## 安装
27
29
 
28
30
  ```bash
29
- npm install @labacacia/nps-sdk
31
+ npm install @labacacia/nps-sdk@alpha
30
32
  ```
31
33
 
32
34
  > **对等依赖:** Node.js 22+
package/README.md CHANGED
@@ -9,6 +9,8 @@ Part of the [LabAcacia](https://github.com/LabAcacia) / INNO LOTUS PTY LTD open-
9
9
 
10
10
  **v1.0.0-alpha.6 — RFC-0002 cross-SDK port (third language)** · 5 protocols · 271 tests · ≥ 98% coverage
11
11
 
12
+ > npm registry note: `@labacacia/nps-sdk@1.0.0-alpha.6` is deprecated because the published tarball omitted `dist/`. The `alpha` dist-tag currently resolves to `1.0.0-alpha.5`; use the GitHub `v1.0.0-alpha.6` tag for source until the next npm prerelease.
13
+
12
14
  | Protocol | Class | Status |
13
15
  |----------|-------|--------|
14
16
  | NCP — Neural Communication Protocol | Framing, codec | ✅ |
@@ -26,7 +28,7 @@ Part of the [LabAcacia](https://github.com/LabAcacia) / INNO LOTUS PTY LTD open-
26
28
  ## Installation
27
29
 
28
30
  ```bash
29
- npm install @labacacia/nps-sdk
31
+ npm install @labacacia/nps-sdk@alpha
30
32
  ```
31
33
 
32
34
  > **Peer requirement:** Node.js 22+
@@ -0,0 +1,42 @@
1
+ import type { AnchorFrame } from "../ncp/frames/anchor-frame.js";
2
+ /**
3
+ * AnchorFrame cache with:
4
+ * - TTL-based expiry (NPS-1 §5.3)
5
+ * - LRU eviction at maxSize (NPS-1 §9, default 1000)
6
+ * - Anchor poisoning detection (NPS-1 §7.2)
7
+ */
8
+ export declare class AnchorCache {
9
+ private readonly cache;
10
+ private readonly maxSize;
11
+ private readonly getNow;
12
+ constructor(options?: {
13
+ maxSize?: number;
14
+ getNow?: () => number;
15
+ });
16
+ /**
17
+ * Cache an AnchorFrame.
18
+ *
19
+ * - ttl=0: frame is valid but not cached (NPS-1 §4.1)
20
+ * - Same anchor_id + same schema: idempotent (no-op)
21
+ * - Same anchor_id + different schema: NCP-ANCHOR-ID-MISMATCH (poison detection)
22
+ *
23
+ * @throws {NcpError} NCP-ANCHOR-ID-MISMATCH on anchor poisoning.
24
+ */
25
+ set(frame: AnchorFrame): void;
26
+ /**
27
+ * Get a cached AnchorFrame by anchor_id.
28
+ *
29
+ * @returns The cached frame, or null if not found or expired.
30
+ */
31
+ get(anchorId: string): AnchorFrame | null;
32
+ /**
33
+ * Get a cached AnchorFrame, throwing if not found.
34
+ * @throws {NcpError} NCP-ANCHOR-NOT-FOUND if not in cache or expired.
35
+ */
36
+ getRequired(anchorId: string): AnchorFrame;
37
+ /** Current cache size. */
38
+ get size(): number;
39
+ /** Evict the least recently accessed entry. */
40
+ private evictLru;
41
+ }
42
+ //# sourceMappingURL=anchor-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchor-cache.d.ts","sourceRoot":"","sources":["../../src/core/anchor-cache.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAQjE;;;;;GAKG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IACvD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;gBAE1B,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAA;KAAE;IAKjE;;;;;;;;OAQG;IACH,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAiC7B;;;;OAIG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAczC;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW;IAW1C,0BAA0B;IAC1B,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,+CAA+C;IAC/C,OAAO,CAAC,QAAQ;CAejB"}
@@ -0,0 +1,104 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 LabAcacia / INNO LOTUS PTY LTD
3
+ //
4
+ // AnchorCache — Schema cache with TTL, LRU eviction, poison detection
5
+ // NPS-1 §5.3, §7.2, §9
6
+ import { NcpError } from "./frame-header.js";
7
+ /**
8
+ * AnchorFrame cache with:
9
+ * - TTL-based expiry (NPS-1 §5.3)
10
+ * - LRU eviction at maxSize (NPS-1 §9, default 1000)
11
+ * - Anchor poisoning detection (NPS-1 §7.2)
12
+ */
13
+ export class AnchorCache {
14
+ cache = new Map();
15
+ maxSize;
16
+ getNow;
17
+ constructor(options) {
18
+ this.maxSize = options?.maxSize ?? 1000;
19
+ this.getNow = options?.getNow ?? (() => Date.now());
20
+ }
21
+ /**
22
+ * Cache an AnchorFrame.
23
+ *
24
+ * - ttl=0: frame is valid but not cached (NPS-1 §4.1)
25
+ * - Same anchor_id + same schema: idempotent (no-op)
26
+ * - Same anchor_id + different schema: NCP-ANCHOR-ID-MISMATCH (poison detection)
27
+ *
28
+ * @throws {NcpError} NCP-ANCHOR-ID-MISMATCH on anchor poisoning.
29
+ */
30
+ set(frame) {
31
+ // ttl=0 means use once, don't cache
32
+ if (frame.ttl === 0)
33
+ return;
34
+ const existing = this.cache.get(frame.anchor_id);
35
+ if (existing) {
36
+ // Poison detection: same ID, different schema
37
+ const existingJson = JSON.stringify(existing.frame.schema);
38
+ const newJson = JSON.stringify(frame.schema);
39
+ if (existingJson !== newJson) {
40
+ throw new NcpError("NCP-ANCHOR-ID-MISMATCH", `Anchor poisoning detected: anchor_id ${frame.anchor_id} received with different schema`);
41
+ }
42
+ // Same schema — idempotent, update access time
43
+ existing.lastAccessed = this.getNow();
44
+ return;
45
+ }
46
+ // LRU eviction if at capacity
47
+ if (this.cache.size >= this.maxSize) {
48
+ this.evictLru();
49
+ }
50
+ const ttlMs = (frame.ttl ?? 3600) * 1000;
51
+ this.cache.set(frame.anchor_id, {
52
+ frame,
53
+ expiresAt: this.getNow() + ttlMs,
54
+ lastAccessed: this.getNow(),
55
+ });
56
+ }
57
+ /**
58
+ * Get a cached AnchorFrame by anchor_id.
59
+ *
60
+ * @returns The cached frame, or null if not found or expired.
61
+ */
62
+ get(anchorId) {
63
+ const entry = this.cache.get(anchorId);
64
+ if (!entry)
65
+ return null;
66
+ // Check TTL expiry
67
+ if (this.getNow() >= entry.expiresAt) {
68
+ this.cache.delete(anchorId);
69
+ return null;
70
+ }
71
+ entry.lastAccessed = this.getNow();
72
+ return entry.frame;
73
+ }
74
+ /**
75
+ * Get a cached AnchorFrame, throwing if not found.
76
+ * @throws {NcpError} NCP-ANCHOR-NOT-FOUND if not in cache or expired.
77
+ */
78
+ getRequired(anchorId) {
79
+ const frame = this.get(anchorId);
80
+ if (!frame) {
81
+ throw new NcpError("NCP-ANCHOR-NOT-FOUND", `Schema anchor ${anchorId} not found in cache`);
82
+ }
83
+ return frame;
84
+ }
85
+ /** Current cache size. */
86
+ get size() {
87
+ return this.cache.size;
88
+ }
89
+ /** Evict the least recently accessed entry. */
90
+ evictLru() {
91
+ let oldestKey;
92
+ let oldestTime = Infinity;
93
+ for (const [key, entry] of this.cache) {
94
+ if (entry.lastAccessed < oldestTime) {
95
+ oldestTime = entry.lastAccessed;
96
+ oldestKey = key;
97
+ }
98
+ }
99
+ if (oldestKey) {
100
+ this.cache.delete(oldestKey);
101
+ }
102
+ }
103
+ }
104
+ //# sourceMappingURL=anchor-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchor-cache.js","sourceRoot":"","sources":["../../src/core/anchor-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { AnchorFrame, FrameSchema } from "../ncp/frames.js";
2
+ export declare class AnchorFrameCache {
3
+ private readonly _store;
4
+ clock: () => number;
5
+ set(frame: AnchorFrame): string;
6
+ get(anchorId: string): AnchorFrame | undefined;
7
+ getRequired(anchorId: string): AnchorFrame;
8
+ invalidate(anchorId: string): void;
9
+ get size(): number;
10
+ static computeAnchorId(schema: FrameSchema): string;
11
+ private _evictExpired;
12
+ private static _schemasEqual;
13
+ }
14
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEjE,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgE;IAGvF,KAAK,EAAE,MAAM,MAAM,CAAoB;IAIvC,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM;IAmB/B,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAU9C,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW;IAM1C,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAIlC,IAAI,IAAI,IAAI,MAAM,CAGjB;IAID,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM;IAiBnD,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,MAAM,CAAC,aAAa;CAG7B"}
@@ -0,0 +1,80 @@
1
+ // Copyright 2026 INNO LOTUS PTY LTD
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * AnchorFrameCache — in-process cache for AnchorFrame instances (NPS-1 §4.1).
5
+ */
6
+ import { createHash } from "node:crypto";
7
+ import { NpsAnchorNotFoundError, NpsAnchorPoisonError } from "./exceptions.js";
8
+ export class AnchorFrameCache {
9
+ _store = new Map();
10
+ // Allow clock injection for testing
11
+ clock = () => Date.now();
12
+ // ── Public API ────────────────────────────────────────────────────────────
13
+ set(frame) {
14
+ const anchorId = frame.anchorId.startsWith("sha256:")
15
+ ? frame.anchorId
16
+ : AnchorFrameCache.computeAnchorId(frame.schema);
17
+ const existing = this._store.get(anchorId);
18
+ if (existing !== undefined && this.clock() < existing.expiresAt) {
19
+ if (!AnchorFrameCache._schemasEqual(existing.frame.schema, frame.schema)) {
20
+ throw new NpsAnchorPoisonError(anchorId);
21
+ }
22
+ // Same schema — idempotent; refresh TTL below
23
+ }
24
+ const ttlMs = (frame.ttl ?? 3600) * 1000;
25
+ const expiresAt = this.clock() + ttlMs;
26
+ this._store.set(anchorId, { frame, expiresAt });
27
+ return anchorId;
28
+ }
29
+ get(anchorId) {
30
+ const entry = this._store.get(anchorId);
31
+ if (entry === undefined)
32
+ return undefined;
33
+ if (this.clock() > entry.expiresAt) {
34
+ this._store.delete(anchorId);
35
+ return undefined;
36
+ }
37
+ return entry.frame;
38
+ }
39
+ getRequired(anchorId) {
40
+ const frame = this.get(anchorId);
41
+ if (frame === undefined)
42
+ throw new NpsAnchorNotFoundError(anchorId);
43
+ return frame;
44
+ }
45
+ invalidate(anchorId) {
46
+ this._store.delete(anchorId);
47
+ }
48
+ get size() {
49
+ this._evictExpired();
50
+ return this._store.size;
51
+ }
52
+ // ── Static helpers ────────────────────────────────────────────────────────
53
+ static computeAnchorId(schema) {
54
+ const sorted = [...schema.fields]
55
+ .map((f) => {
56
+ const obj = { name: f.name, type: f.type };
57
+ if (f.semantic !== undefined)
58
+ obj["semantic"] = f.semantic;
59
+ if (f.nullable !== undefined)
60
+ obj["nullable"] = f.nullable;
61
+ return obj;
62
+ })
63
+ .sort((a, b) => String(a["name"]).localeCompare(String(b["name"])));
64
+ const canonical = JSON.stringify(sorted);
65
+ const digest = createHash("sha256").update(canonical, "utf8").digest("hex");
66
+ return `sha256:${digest}`;
67
+ }
68
+ // ── Private ───────────────────────────────────────────────────────────────
69
+ _evictExpired() {
70
+ const now = this.clock();
71
+ for (const [k, entry] of this._store) {
72
+ if (now > entry.expiresAt)
73
+ this._store.delete(k);
74
+ }
75
+ }
76
+ static _schemasEqual(a, b) {
77
+ return AnchorFrameCache.computeAnchorId(a) === AnchorFrameCache.computeAnchorId(b);
78
+ }
79
+ }
80
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * JCS (RFC 8785) canonical JSON stringify.
3
+ * Used for AnchorFrame anchor_id computation.
4
+ */
5
+ export declare function jcsStringify(obj: unknown): string;
6
+ /**
7
+ * Sorted-key JSON stringify — matches Python's
8
+ * `json.dumps(obj, sort_keys=True, separators=(",",":"))`.
9
+ * Used for NIP signing.
10
+ */
11
+ export declare function sortKeysStringify(obj: unknown): string;
12
+ //# sourceMappingURL=canonical-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical-json.d.ts","sourceRoot":"","sources":["../../src/core/canonical-json.ts"],"names":[],"mappings":"AAgBA;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAMjD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAEtD"}
@@ -0,0 +1,44 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 LabAcacia / INNO LOTUS PTY LTD
3
+ //
4
+ // Canonical JSON helpers — two distinct serialisation paths used in NPS.
5
+ //
6
+ // AnchorFrame uses JCS (RFC 8785) for anchor_id hashing → jcsStringify.
7
+ // NIP signing uses Python-compatible sorted-key JSON → sortKeysStringify.
8
+ import canonicalizeImport from "canonicalize";
9
+ // `canonicalize` is a CJS module whose default export resolves to a namespace
10
+ // under NodeNext. Cast once to the call signature its .d.ts promises.
11
+ const canonicalize = canonicalizeImport;
12
+ /**
13
+ * JCS (RFC 8785) canonical JSON stringify.
14
+ * Used for AnchorFrame anchor_id computation.
15
+ */
16
+ export function jcsStringify(obj) {
17
+ const result = canonicalize(obj);
18
+ if (result === undefined) {
19
+ throw new Error("canonicalize returned undefined for input");
20
+ }
21
+ return result;
22
+ }
23
+ /**
24
+ * Sorted-key JSON stringify — matches Python's
25
+ * `json.dumps(obj, sort_keys=True, separators=(",",":"))`.
26
+ * Used for NIP signing.
27
+ */
28
+ export function sortKeysStringify(obj) {
29
+ return JSON.stringify(sortKeys(obj));
30
+ }
31
+ function sortKeys(value) {
32
+ if (Array.isArray(value)) {
33
+ return value.map(sortKeys);
34
+ }
35
+ if (value !== null && typeof value === "object") {
36
+ const sorted = {};
37
+ for (const key of Object.keys(value).sort()) {
38
+ sorted[key] = sortKeys(value[key]);
39
+ }
40
+ return sorted;
41
+ }
42
+ return value;
43
+ }
44
+ //# sourceMappingURL=canonical-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical-json.js","sourceRoot":"","sources":["../../src/core/canonical-json.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,oDAAoD;AACpD,EAAE;AACF,yEAAyE;AACzE,EAAE;AACF,wEAAwE;AACxE,0EAA0E;AAE1E,OAAO,kBAAkB,MAAM,cAAc,CAAC;AAE9C,8EAA8E;AAC9E,sEAAsE;AACtE,MAAM,YAAY,GAAG,kBAEE,CAAC;AAExB;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAe,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YACtD,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAE,KAAiC,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}