@labacacia/nps-sdk 1.0.0-alpha.3 → 1.0.0-alpha.5

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 (241) hide show
  1. package/CHANGELOG.cn.md +73 -0
  2. package/CHANGELOG.md +82 -0
  3. package/README.cn.md +17 -4
  4. package/README.md +17 -4
  5. package/dist/core/anchor-cache.js +104 -0
  6. package/dist/core/anchor-cache.js.map +1 -0
  7. package/dist/core/cache.js +80 -0
  8. package/dist/core/cache.js.map +1 -0
  9. package/dist/core/canonical-json.js +44 -0
  10. package/dist/core/canonical-json.js.map +1 -0
  11. package/dist/core/codec.js +119 -0
  12. package/dist/core/codec.js.map +1 -0
  13. package/dist/core/codecs/index.js +6 -0
  14. package/dist/core/codecs/index.js.map +1 -0
  15. package/dist/core/codecs/ncp-codec.js +93 -0
  16. package/dist/core/codecs/ncp-codec.js.map +1 -0
  17. package/dist/core/codecs/tier1-json-codec.js +28 -0
  18. package/dist/core/codecs/tier1-json-codec.js.map +1 -0
  19. package/dist/core/codecs/tier2-msgpack-codec.js +26 -0
  20. package/dist/core/codecs/tier2-msgpack-codec.js.map +1 -0
  21. package/dist/core/crypto-provider.js +10 -0
  22. package/dist/core/crypto-provider.js.map +1 -0
  23. package/dist/core/exceptions.js +52 -0
  24. package/dist/core/exceptions.js.map +1 -0
  25. package/dist/core/frame-header.js +185 -0
  26. package/dist/core/frame-header.js.map +1 -0
  27. package/dist/core/frame-registry.js +63 -0
  28. package/dist/core/frame-registry.js.map +1 -0
  29. package/dist/core/frames.js +154 -0
  30. package/dist/core/frames.js.map +1 -0
  31. package/dist/core/index.js +21 -405
  32. package/dist/core/index.js.map +1 -1
  33. package/dist/core/registry.js +17 -0
  34. package/dist/core/registry.js.map +1 -0
  35. package/dist/core/status-codes.d.ts +1 -0
  36. package/dist/core/status-codes.d.ts.map +1 -1
  37. package/dist/core/status-codes.js +39 -0
  38. package/dist/core/status-codes.js.map +1 -0
  39. package/dist/index.d.ts +1 -1
  40. package/dist/index.js +9 -5
  41. package/dist/index.js.map +1 -1
  42. package/dist/ncp/frames/anchor-frame.js +54 -0
  43. package/dist/ncp/frames/anchor-frame.js.map +1 -0
  44. package/dist/ncp/frames/caps-frame.js +29 -0
  45. package/dist/ncp/frames/caps-frame.js.map +1 -0
  46. package/dist/ncp/frames/diff-frame.js +37 -0
  47. package/dist/ncp/frames/diff-frame.js.map +1 -0
  48. package/dist/ncp/frames/error-frame.js +13 -0
  49. package/dist/ncp/frames/error-frame.js.map +1 -0
  50. package/dist/ncp/frames/hello-frame.js +25 -0
  51. package/dist/ncp/frames/hello-frame.js.map +1 -0
  52. package/dist/ncp/frames/stream-frame.js +18 -0
  53. package/dist/ncp/frames/stream-frame.js.map +1 -0
  54. package/dist/ncp/frames.js +192 -0
  55. package/dist/ncp/frames.js.map +1 -0
  56. package/dist/ncp/handshake.js +80 -0
  57. package/dist/ncp/handshake.js.map +1 -0
  58. package/dist/ncp/index.d.ts +1 -0
  59. package/dist/ncp/index.d.ts.map +1 -1
  60. package/dist/ncp/index.js +13 -368
  61. package/dist/ncp/index.js.map +1 -1
  62. package/dist/ncp/ncp-error-codes.d.ts +1 -0
  63. package/dist/ncp/ncp-error-codes.d.ts.map +1 -1
  64. package/dist/ncp/ncp-error-codes.js +34 -0
  65. package/dist/ncp/ncp-error-codes.js.map +1 -0
  66. package/dist/ncp/ncp-patch-format.js +13 -0
  67. package/dist/ncp/ncp-patch-format.js.map +1 -0
  68. package/dist/ncp/preamble.d.ts +47 -0
  69. package/dist/ncp/preamble.d.ts.map +1 -0
  70. package/dist/ncp/preamble.js +74 -0
  71. package/dist/ncp/preamble.js.map +1 -0
  72. package/dist/ncp/registry.js +13 -0
  73. package/dist/ncp/registry.js.map +1 -0
  74. package/dist/ncp/stream-manager.js +163 -0
  75. package/dist/ncp/stream-manager.js.map +1 -0
  76. package/dist/ndp/dns-txt.d.ts +35 -0
  77. package/dist/ndp/dns-txt.d.ts.map +1 -0
  78. package/dist/ndp/dns-txt.js +67 -0
  79. package/dist/ndp/dns-txt.js.map +1 -0
  80. package/dist/ndp/frames.js +87 -0
  81. package/dist/ndp/frames.js.map +1 -0
  82. package/dist/ndp/index.d.ts +1 -0
  83. package/dist/ndp/index.d.ts.map +1 -1
  84. package/dist/ndp/index.js +7 -223
  85. package/dist/ndp/index.js.map +1 -1
  86. package/dist/ndp/ndp-registry.d.ts +2 -0
  87. package/dist/ndp/ndp-registry.d.ts.map +1 -1
  88. package/dist/ndp/ndp-registry.js +104 -0
  89. package/dist/ndp/ndp-registry.js.map +1 -0
  90. package/dist/ndp/registry.js +10 -0
  91. package/dist/ndp/registry.js.map +1 -0
  92. package/dist/ndp/validator.js +48 -0
  93. package/dist/ndp/validator.js.map +1 -0
  94. package/dist/nip/acme/client.d.ts +31 -0
  95. package/dist/nip/acme/client.d.ts.map +1 -0
  96. package/dist/nip/acme/client.js +136 -0
  97. package/dist/nip/acme/client.js.map +1 -0
  98. package/dist/nip/acme/index.d.ts +6 -0
  99. package/dist/nip/acme/index.d.ts.map +1 -0
  100. package/dist/nip/acme/index.js +8 -0
  101. package/dist/nip/acme/index.js.map +1 -0
  102. package/dist/nip/acme/jws.d.ts +31 -0
  103. package/dist/nip/acme/jws.d.ts.map +1 -0
  104. package/dist/nip/acme/jws.js +76 -0
  105. package/dist/nip/acme/jws.js.map +1 -0
  106. package/dist/nip/acme/messages.d.ts +71 -0
  107. package/dist/nip/acme/messages.d.ts.map +1 -0
  108. package/dist/nip/acme/messages.js +4 -0
  109. package/dist/nip/acme/messages.js.map +1 -0
  110. package/dist/nip/acme/server.d.ts +41 -0
  111. package/dist/nip/acme/server.d.ts.map +1 -0
  112. package/dist/nip/acme/server.js +458 -0
  113. package/dist/nip/acme/server.js.map +1 -0
  114. package/dist/nip/acme/wire.d.ts +19 -0
  115. package/dist/nip/acme/wire.d.ts.map +1 -0
  116. package/dist/nip/acme/wire.js +21 -0
  117. package/dist/nip/acme/wire.js.map +1 -0
  118. package/dist/nip/assurance-level.d.ts +19 -0
  119. package/dist/nip/assurance-level.d.ts.map +1 -0
  120. package/dist/nip/assurance-level.js +38 -0
  121. package/dist/nip/assurance-level.js.map +1 -0
  122. package/dist/nip/cert-format.d.ts +5 -0
  123. package/dist/nip/cert-format.d.ts.map +1 -0
  124. package/dist/nip/cert-format.js +6 -0
  125. package/dist/nip/cert-format.js.map +1 -0
  126. package/dist/nip/error-codes.d.ts +25 -0
  127. package/dist/nip/error-codes.d.ts.map +1 -0
  128. package/dist/nip/error-codes.js +32 -0
  129. package/dist/nip/error-codes.js.map +1 -0
  130. package/dist/nip/frames.d.ts +10 -1
  131. package/dist/nip/frames.d.ts.map +1 -1
  132. package/dist/nip/frames.js +106 -0
  133. package/dist/nip/frames.js.map +1 -0
  134. package/dist/nip/identity.js +94 -0
  135. package/dist/nip/identity.js.map +1 -0
  136. package/dist/nip/index.d.ts +6 -0
  137. package/dist/nip/index.d.ts.map +1 -1
  138. package/dist/nip/index.js +12 -187
  139. package/dist/nip/index.js.map +1 -1
  140. package/dist/nip/registry.js +10 -0
  141. package/dist/nip/registry.js.map +1 -0
  142. package/dist/nip/verifier.d.ts +23 -0
  143. package/dist/nip/verifier.d.ts.map +1 -0
  144. package/dist/nip/verifier.js +90 -0
  145. package/dist/nip/verifier.js.map +1 -0
  146. package/dist/nip/x509/builder.d.ts +35 -0
  147. package/dist/nip/x509/builder.d.ts.map +1 -0
  148. package/dist/nip/x509/builder.js +59 -0
  149. package/dist/nip/x509/builder.js.map +1 -0
  150. package/dist/nip/x509/index.d.ts +4 -0
  151. package/dist/nip/x509/index.d.ts.map +1 -0
  152. package/dist/nip/x509/index.js +6 -0
  153. package/dist/nip/x509/index.js.map +1 -0
  154. package/dist/nip/x509/oids.d.ts +17 -0
  155. package/dist/nip/x509/oids.d.ts.map +1 -0
  156. package/dist/nip/x509/oids.js +23 -0
  157. package/dist/nip/x509/oids.js.map +1 -0
  158. package/dist/nip/x509/verifier.d.ts +26 -0
  159. package/dist/nip/x509/verifier.d.ts.map +1 -0
  160. package/dist/nip/x509/verifier.js +171 -0
  161. package/dist/nip/x509/verifier.js.map +1 -0
  162. package/dist/nop/client.js +90 -0
  163. package/dist/nop/client.js.map +1 -0
  164. package/dist/nop/frames.js +148 -0
  165. package/dist/nop/frames.js.map +1 -0
  166. package/dist/nop/index.js +6 -789
  167. package/dist/nop/index.js.map +1 -1
  168. package/dist/nop/models.js +50 -0
  169. package/dist/nop/models.js.map +1 -0
  170. package/dist/nop/nop-types.js +44 -0
  171. package/dist/nop/nop-types.js.map +1 -0
  172. package/dist/nop/registry.js +11 -0
  173. package/dist/nop/registry.js.map +1 -0
  174. package/dist/nwp/client.js +101 -0
  175. package/dist/nwp/client.js.map +1 -0
  176. package/dist/nwp/error-codes.d.ts +42 -0
  177. package/dist/nwp/error-codes.d.ts.map +1 -0
  178. package/dist/nwp/error-codes.js +53 -0
  179. package/dist/nwp/error-codes.js.map +1 -0
  180. package/dist/nwp/frames.js +81 -0
  181. package/dist/nwp/frames.js.map +1 -0
  182. package/dist/nwp/index.d.ts +1 -0
  183. package/dist/nwp/index.d.ts.map +1 -1
  184. package/dist/nwp/index.js +6 -693
  185. package/dist/nwp/index.js.map +1 -1
  186. package/dist/nwp/registry.js +9 -0
  187. package/dist/nwp/registry.js.map +1 -0
  188. package/dist/setup.js +29 -0
  189. package/dist/setup.js.map +1 -0
  190. package/doc/nps-sdk.nip.cn.md +30 -0
  191. package/doc/nps-sdk.nip.md +30 -0
  192. package/doc/nps-sdk.nwp.cn.md +71 -0
  193. package/doc/nps-sdk.nwp.md +71 -0
  194. package/package.json +2 -1
  195. package/src/core/status-codes.ts +1 -0
  196. package/src/index.ts +1 -1
  197. package/src/ncp/index.ts +1 -0
  198. package/src/ncp/ncp-error-codes.ts +2 -0
  199. package/src/ncp/preamble.ts +79 -0
  200. package/src/ndp/dns-txt.ts +86 -0
  201. package/src/ndp/index.ts +1 -0
  202. package/src/ndp/ndp-registry.ts +34 -0
  203. package/src/nip/acme/client.ts +185 -0
  204. package/src/nip/acme/index.ts +8 -0
  205. package/src/nip/acme/jws.ts +109 -0
  206. package/src/nip/acme/messages.ts +85 -0
  207. package/src/nip/acme/server.ts +480 -0
  208. package/src/nip/acme/wire.ts +24 -0
  209. package/src/nip/assurance-level.ts +40 -0
  210. package/src/nip/cert-format.ts +9 -0
  211. package/src/nip/error-codes.ts +38 -0
  212. package/src/nip/frames.ts +35 -3
  213. package/src/nip/index.ts +8 -0
  214. package/src/nip/verifier.ts +122 -0
  215. package/src/nip/x509/builder.ts +91 -0
  216. package/src/nip/x509/index.ts +6 -0
  217. package/src/nip/x509/oids.ts +28 -0
  218. package/src/nip/x509/verifier.ts +214 -0
  219. package/src/nop/client.ts +1 -1
  220. package/src/nwp/client.ts +4 -4
  221. package/src/nwp/error-codes.ts +62 -0
  222. package/src/nwp/index.ts +1 -0
  223. package/tests/_rfc0002-keys.ts +57 -0
  224. package/tests/ncp/preamble.test.ts +93 -0
  225. package/tests/ndp.test.ts +106 -0
  226. package/tests/nip-acme-agent01.test.ts +192 -0
  227. package/tests/nip-x509.test.ts +280 -0
  228. package/dist/core/index.cjs +0 -452
  229. package/dist/core/index.cjs.map +0 -1
  230. package/dist/index.cjs +0 -8
  231. package/dist/index.cjs.map +0 -1
  232. package/dist/ncp/index.cjs +0 -388
  233. package/dist/ncp/index.cjs.map +0 -1
  234. package/dist/ndp/index.cjs +0 -252
  235. package/dist/ndp/index.cjs.map +0 -1
  236. package/dist/nip/index.cjs +0 -214
  237. package/dist/nip/index.cjs.map +0 -1
  238. package/dist/nop/index.cjs +0 -823
  239. package/dist/nop/index.cjs.map +0 -1
  240. package/dist/nwp/index.cjs +0 -720
  241. package/dist/nwp/index.cjs.map +0 -1
package/CHANGELOG.cn.md CHANGED
@@ -8,6 +8,77 @@
8
8
 
9
9
  ---
10
10
 
11
+ ## [1.0.0-alpha.5] —— 2026-05-01
12
+
13
+ ### 新增
14
+
15
+ - **NWP 错误码常量** —— 新增 `NwpErrorCodes` 命名空间,从 `@labacacia/nps-sdk/nwp` 导出,包含全部 30 个 NWP wire 错误码(auth、query、action、task、subscribe、infrastructure、manifest、topology、reserved-type)。此前版本均未提供。
16
+ - **`NpsStatusCodes.NPS_SERVER_UNSUPPORTED`** —— 在 `src/core/status-codes.ts` 新增状态码 `"NPS-SERVER-UNSUPPORTED"`(HTTP 501),符合 spec/status-codes.md alpha.5 更新。
17
+ - **`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。
18
+
19
+ ### 变更
20
+
21
+ - **`AssuranceLevel.fromWire("")` 返回 `Anonymous`** —— `if (wire == null)` 改为 `if (!wire)`,使 `""` 返回 `Anonymous` 而非 `Unknown`(spec §5.1.1 向后兼容修复)。
22
+ - **版本升至 `1.0.0-alpha.5`** —— 与 NPS 套件 alpha.5 同步。
23
+
24
+ ### 修复
25
+
26
+ - **`REPUTATION_GOSSIP_FORK` / `REPUTATION_GOSSIP_SIG_INVALID`** —— 向 `src/nip/error-codes.ts` 新增两个 NIP 声誉 gossip 错误码(RFC-0004 Phase 3)。
27
+
28
+ ---
29
+
30
+ ## [1.0.0-alpha.4] —— 2026-04-30
31
+
32
+ ### 新增
33
+
34
+ - **NPS-RFC-0001 Phase 2 —— NCP 连接前导(TypeScript helper 跟进)。**
35
+ `src/ncp/preamble.ts` 暴露 `writePreamble(stream)` /
36
+ `readPreamble(stream)`,往返字面量 `b"NPS/1.0\n"` 哨兵;
37
+ `tests/ncp/preamble.test.ts` 覆盖。让 TypeScript SDK 与 .NET /
38
+ Python / Go / Java 在 alpha.4 的 preamble helper 持平。
39
+ - **NPS-RFC-0002 Phase A/B —— X.509 NID 证书 + ACME `agent-01`
40
+ (TypeScript 端口)。** 新增 `src/nip/` 子模块:
41
+ - `nip/x509/` —— X.509 NID 证书 builder + verifier
42
+ (`x509.Builder`、`x509.Verifier`)。
43
+ - `nip/acme/` —— ACME `agent-01` 客户端 + 服务端参考实现
44
+ (`AcmeServer`、`AcmeClient`);按 NPS-RFC-0002 Phase B 的 JWS
45
+ 签名 wire 包络。
46
+ - `nip/assurance-level.ts` —— Agent 身份保证等级
47
+ (`anonymous` / `attested` / `verified`),承接 NPS-RFC-0003。
48
+ - `nip/cert-format.ts` —— IdentFrame `cert_format` 判别器
49
+ (`v1` Ed25519 vs. `x509`)。
50
+ - `nip/error-codes.ts` —— NIP 错误码命名空间。
51
+ - `nip/verifier.ts` —— dual-trust IdentFrame 验证器(v1 + X.509)。
52
+ - 20 个新测试覆盖 preamble 往返、X.509 签发 + 解析、dual-trust 验证、
53
+ ACME agent-01 全流程。总数:284 tests 全绿(alpha.3 时 264)。
54
+
55
+ ### 变更
56
+
57
+ - 分发版本升至 `1.0.0-alpha.4`。
58
+ - `src/nip/frames.ts` —— IdentFrame wire 形状扩展,可携带可选的
59
+ `cert_format` 判别器 + `x509_chain` 字段,与 v1 Ed25519 字段并存。
60
+ alpha.3 写出的 v1 IdentFrame 仍可被 alpha.4 验签。
61
+
62
+ ### npm 发布说明
63
+
64
+ - 本仓库 / tag 是 `@labacacia/nps-sdk` `1.0.0-alpha.4` 的权威参考。
65
+ 延续 alpha.3 的情况,npm publish 可能需要带 2FA-bypass 的 granular
66
+ access token —— 如果 npm registry 上的版本暂时落后于本仓库 tag,
67
+ 以 tag 为准;下一次 registry cut 后 `npm install` 即可解析到本
68
+ commit。
69
+
70
+ ### 套件级 alpha.4 要点
71
+
72
+ - **NPS-RFC-0002 X.509 + ACME** —— 完整跨 SDK 端口波(.NET / Java /
73
+ Python / TypeScript / Go / Rust)。
74
+ - **NPS-CR-0002 —— Anchor Node topology 查询** —— `topology.snapshot`
75
+ / `topology.stream`(.NET 参考 + L2 conformance)。TypeScript 消费
76
+ 侧 helper 后续版本跟进。
77
+ - **`nps-registry` SQLite 实仓** + **`nps-ledger` Phase 2**
78
+ (RFC 9162 Merkle + STH + inclusion proof)已在 daemon 仓库交付。
79
+
80
+ ---
81
+
11
82
  ## [1.0.0-alpha.3] —— 2026-04-25
12
83
 
13
84
  ### Changed
@@ -52,6 +123,8 @@
52
123
 
53
124
  作为 NPS 套件 `v1.0.0-alpha.1` 的一部分首次公开 alpha。
54
125
 
126
+ [1.0.0-alpha.5]: https://github.com/labacacia/NPS-sdk-ts/releases/tag/v1.0.0-alpha.5
127
+ [1.0.0-alpha.4]: https://gitee.com/labacacia/NPS-sdk-ts/releases/tag/v1.0.0-alpha.4
55
128
  [1.0.0-alpha.3]: https://github.com/LabAcacia/NPS-Dev/releases/tag/v1.0.0-alpha.3
56
129
  [1.0.0-alpha.2]: https://github.com/LabAcacia/NPS-Dev/releases/tag/v1.0.0-alpha.2
57
130
  [1.0.0-alpha.1]: https://github.com/LabAcacia/NPS-Dev/releases/tag/v1.0.0-alpha.1
package/CHANGELOG.md CHANGED
@@ -8,6 +8,86 @@ 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.5] — 2026-05-01
12
+
13
+ ### Added
14
+
15
+ - **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.
16
+ - **`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.
17
+ - **`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.
18
+
19
+ ### Changed
20
+
21
+ - **`AssuranceLevel.fromWire("")` returns `Anonymous`** — `if (wire == null)` changed to `if (!wire)` so `""` returns `Anonymous` instead of `Unknown` (spec §5.1.1 backward-compat fix).
22
+ - **Version bump to `1.0.0-alpha.5`** — synchronized with NPS suite alpha.5 release.
23
+
24
+ ### Fixed
25
+
26
+ - **`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).
27
+
28
+ ---
29
+
30
+ ## [1.0.0-alpha.4] — 2026-04-30
31
+
32
+ ### Added
33
+
34
+ - **NPS-RFC-0001 Phase 2 — NCP connection preamble (TypeScript helper
35
+ parity).** `src/ncp/preamble.ts` exposes `writePreamble(stream)` and
36
+ `readPreamble(stream)` round-tripping the literal `b"NPS/1.0\n"`
37
+ sentinel; matched by `tests/ncp/preamble.test.ts`. Brings TypeScript
38
+ in line with the .NET / Python / Go / Java preamble helpers shipped
39
+ at alpha.4.
40
+ - **NPS-RFC-0002 Phase A/B — X.509 NID certificates + ACME `agent-01`
41
+ (TypeScript port).** New surface under `src/nip/`:
42
+ - `nip/x509/` — X.509 NID certificate builder + verifier
43
+ (`x509.Builder`, `x509.Verifier`).
44
+ - `nip/acme/` — ACME `agent-01` client + server reference
45
+ (`AcmeServer`, `AcmeClient`); JWS-signed wire envelope per
46
+ NPS-RFC-0002 Phase B.
47
+ - `nip/assurance-level.ts` — agent identity assurance levels
48
+ (`anonymous` / `attested` / `verified`) per NPS-RFC-0003.
49
+ - `nip/cert-format.ts` — IdentFrame `cert_format` discriminator
50
+ (`v1` Ed25519 vs. `x509`).
51
+ - `nip/error-codes.ts` — NIP error code namespace strings.
52
+ - `nip/verifier.ts` — dual-trust IdentFrame verifier (v1 + X.509).
53
+ - 20 new tests covering preamble round-trip, X.509 issuance + parsing,
54
+ dual-trust verification, and ACME agent-01 round-trip. Total: 284
55
+ tests green (was 264 at alpha.3).
56
+
57
+ ### Changed
58
+
59
+ - Distribution version bumped to `1.0.0-alpha.4`.
60
+ - `src/nip/frames.ts` — IdentFrame wire shape extended with optional
61
+ `cert_format` discriminator + `x509_chain` field alongside the
62
+ existing v1 Ed25519 fields. v1 IdentFrames written by alpha.3
63
+ consumers continue to verify unchanged.
64
+
65
+ ### Note: npm publish status
66
+
67
+ - This repo / tag is the canonical `1.0.0-alpha.4` reference for
68
+ `@labacacia/nps-sdk`. As at the alpha.3 ship cycle, npm publish
69
+ may require a granular access token with 2FA-bypass enabled — if
70
+ the registry version lags this repo's tag, the tag is the
71
+ authoritative artifact and `npm install` against the next
72
+ registry cut will resolve to this commit.
73
+
74
+ ### Suite-wide highlights at alpha.4
75
+
76
+ - **NPS-RFC-0002 X.509 + ACME** — full cross-SDK port wave (.NET /
77
+ Java / Python / TypeScript / Go / Rust). Servers can now issue
78
+ dual-trust IdentFrames (v1 Ed25519 + X.509 leaf cert chained to a
79
+ self-signed root) and self-onboard NIDs over ACME's `agent-01`
80
+ challenge type.
81
+ - **NPS-CR-0002 — Anchor Node topology queries** — `topology.snapshot`
82
+ / `topology.stream` query types (.NET reference + L2 conformance
83
+ suite). TypeScript consumer-side helpers planned for a later
84
+ release.
85
+ - **`nps-registry` SQLite-backed real registry** + **`nps-ledger`
86
+ Phase 2** (RFC 9162 Merkle + STH + inclusion proofs) shipped in the
87
+ daemon repos.
88
+
89
+ ---
90
+
11
91
  ## [1.0.0-alpha.3] — 2026-04-25
12
92
 
13
93
  ### Changed
@@ -52,6 +132,8 @@ Until NPS reaches v1.0 stable, every repository in the suite is synchronized to
52
132
 
53
133
  First public alpha as part of the NPS suite `v1.0.0-alpha.1` release.
54
134
 
135
+ [1.0.0-alpha.5]: https://github.com/labacacia/NPS-sdk-ts/releases/tag/v1.0.0-alpha.5
136
+ [1.0.0-alpha.4]: https://github.com/labacacia/NPS-sdk-ts/releases/tag/v1.0.0-alpha.4
55
137
  [1.0.0-alpha.3]: https://github.com/LabAcacia/NPS-Dev/releases/tag/v1.0.0-alpha.3
56
138
  [1.0.0-alpha.2]: https://github.com/LabAcacia/NPS-Dev/releases/tag/v1.0.0-alpha.2
57
139
  [1.0.0-alpha.1]: https://github.com/LabAcacia/NPS-Dev/releases/tag/v1.0.0-alpha.1
package/README.cn.md CHANGED
@@ -7,16 +7,29 @@
7
7
 
8
8
  ## 状态
9
9
 
10
- **v1.0.0-alpha.3 Phase 2** · 5 个协议 · 264 个测试 · 覆盖率 ≥ 98%
10
+ **v1.0.0-alpha.5 —— NWP 错误码 + NPS 状态码扩展** · 5 个协议 · 284 个测试 · 覆盖率 ≥ 98%
11
11
 
12
12
  | 协议 | 类 | 状态 |
13
13
  |------|----|------|
14
14
  | NCP — Neural Communication Protocol | 帧、编解码器 | ✅ |
15
- | NWP — Neural Web Protocol | `NwpClient` | ✅ |
16
- | NIP — Neural Identity Protocol | `NipIdentity` | ✅ |
17
- | NDP — Neural Discovery Protocol | `InMemoryNdpRegistry`、`NdpAnnounceValidator` | ✅ |
15
+ | NWP — Neural Web Protocol | `NwpClient`、`NwpErrorCodes` | ✅ |
16
+ | NIP — Neural Identity Protocol | `NipIdentity`、`NipIdentVerifier`(RFC-0002 §8.1 双信任)、`AssuranceLevel`(RFC-0003)、`nip.x509` + `nip.acme` | ✅ |
17
+ | NDP — Neural Discovery Protocol | `InMemoryNdpRegistry`、`NdpAnnounceValidator`、`resolveWithDns`(DNS TXT 回退)、`DnsTxtLookup`、`SystemDnsTxtLookup`、`parseNpsTxtRecord` | ✅ |
18
18
  | NOP — Neural Orchestration Protocol | `NopClient` | ✅ |
19
19
 
20
+ **alpha.5 新增:**
21
+
22
+ - `NwpErrorCodes` —— 从 `@labacacia/nps-sdk/nwp` 导出,包含 30 个 NWP wire 错误码字符串常量(`NWP-AUTH-*`、`NWP-QUERY-*`、`NWP-TOPOLOGY-*`、`NWP-RESERVED-TYPE-UNSUPPORTED` 等)。
23
+ - `NpsStatusCodes.NPS_SERVER_UNSUPPORTED` —— 新状态码 `"NPS-SERVER-UNSUPPORTED"`(HTTP 501)。
24
+ - `NipErrorCodes.REPUTATION_GOSSIP_FORK` / `.REPUTATION_GOSSIP_SIG_INVALID` —— RFC-0004 Phase 3 gossip 错误码。
25
+ - `AssuranceLevel.fromWire("")` 改为返回 `Anonymous`(spec §5.1.1 修复)。
26
+
27
+ **alpha.4 新增** —— 完整的 NPS-RFC-0002 X.509 + ACME `agent-01` NID 证书原语:
28
+
29
+ - `nip.x509` —— `issueLeaf` / `issueRoot` / `verify`(基于 `@peculiar/x509` + 原生 Web Crypto Ed25519)。
30
+ - `nip.acme` —— `AcmeClient` + 进程内 `AcmeServer` + JWS / messages helpers(RFC 8555 + RFC 8037 EdDSA)。
31
+ - `IdentFrame` 扩展非破坏性可选构造参数 `assuranceLevel` / `certFormat` / `certChain`;v1 verifier 忽略新字段。
32
+
20
33
  ## 安装
21
34
 
22
35
  ```bash
package/README.md CHANGED
@@ -7,16 +7,29 @@ Part of the [LabAcacia](https://github.com/LabAcacia) / INNO LOTUS PTY LTD open-
7
7
 
8
8
  ## Status
9
9
 
10
- **v1.0.0-alpha.3Phase 2** · 5 protocols · 264 tests · ≥ 98% coverage
10
+ **v1.0.0-alpha.5NWP error codes + NPS status code extension** · 5 protocols · 284 tests · ≥ 98% coverage
11
11
 
12
12
  | Protocol | Class | Status |
13
13
  |----------|-------|--------|
14
14
  | NCP — Neural Communication Protocol | Framing, codec | ✅ |
15
- | NWP — Neural Web Protocol | `NwpClient` | ✅ |
16
- | NIP — Neural Identity Protocol | `NipIdentity` | ✅ |
17
- | NDP — Neural Discovery Protocol | `InMemoryNdpRegistry`, `NdpAnnounceValidator` | ✅ |
15
+ | NWP — Neural Web Protocol | `NwpClient`, `NwpErrorCodes` | ✅ |
16
+ | NIP — Neural Identity Protocol | `NipIdentity`, `NipIdentVerifier` (RFC-0002 §8.1 dual-trust), `AssuranceLevel` (RFC-0003), `nip.x509` + `nip.acme` | ✅ |
17
+ | NDP — Neural Discovery Protocol | `InMemoryNdpRegistry`, `NdpAnnounceValidator`, `resolveWithDns` (DNS TXT fallback), `DnsTxtLookup`, `SystemDnsTxtLookup`, `parseNpsTxtRecord` | ✅ |
18
18
  | NOP — Neural Orchestration Protocol | `NopClient` | ✅ |
19
19
 
20
+ **alpha.5 additions:**
21
+
22
+ - `NwpErrorCodes` — exported from `@labacacia/nps-sdk/nwp`; 30 NWP wire error code constants (`NWP-AUTH-*`, `NWP-QUERY-*`, `NWP-TOPOLOGY-*`, `NWP-RESERVED-TYPE-UNSUPPORTED`, …).
23
+ - `NpsStatusCodes.NPS_SERVER_UNSUPPORTED` — new `"NPS-SERVER-UNSUPPORTED"` status code (HTTP 501) in `src/core/status-codes.ts`.
24
+ - `NipErrorCodes.REPUTATION_GOSSIP_FORK` / `.REPUTATION_GOSSIP_SIG_INVALID` — RFC-0004 Phase 3 gossip error codes.
25
+ - `AssuranceLevel.fromWire("")` returns `Anonymous` instead of `Unknown` (spec §5.1.1 fix).
26
+
27
+ **alpha.4 additions** — Full NPS-RFC-0002 X.509 + ACME `agent-01` NID certificate primitives:
28
+
29
+ - `nip.x509` — `issueLeaf` / `issueRoot` / `verify` (built on `@peculiar/x509` + native Web Crypto Ed25519).
30
+ - `nip.acme` — `AcmeClient` + in-process `AcmeServer` + JWS / message helpers (RFC 8555 + EdDSA per RFC 8037).
31
+ - `IdentFrame` extended with non-breaking `assuranceLevel` / `certFormat` / `certChain` constructor options; v1 verifiers ignore the new fields.
32
+
20
33
  ## Installation
21
34
 
22
35
  ```bash
@@ -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,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,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"}
@@ -0,0 +1,119 @@
1
+ // Copyright 2026 INNO LOTUS PTY LTD
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * NPS frame codec: Tier-1 (JSON) and Tier-2 (MsgPack) encode/decode,
5
+ * plus the top-level NpsFrameCodec dispatcher.
6
+ */
7
+ import * as msgpack from "@msgpack/msgpack";
8
+ import { NpsCodecError } from "./exceptions.js";
9
+ import { DEFAULT_MAX_PAYLOAD, EncodingTier, FrameFlags, FrameHeader, } from "./frames.js";
10
+ // ── Tier-1 JSON codec ─────────────────────────────────────────────────────────
11
+ export class Tier1JsonCodec {
12
+ encode(frame) {
13
+ try {
14
+ const json = JSON.stringify(frame.toDict());
15
+ return new TextEncoder().encode(json);
16
+ }
17
+ catch (err) {
18
+ throw new NpsCodecError(`Tier-1 JSON encode failed for 0x${frame.frameType.toString(16).padStart(2, "0")}: ${String(err)}`);
19
+ }
20
+ }
21
+ decode(frameType, payload, registry) {
22
+ const cls = registry.resolve(frameType);
23
+ try {
24
+ const text = new TextDecoder().decode(payload);
25
+ const data = JSON.parse(text);
26
+ return cls.fromDict(data);
27
+ }
28
+ catch (err) {
29
+ throw new NpsCodecError(`Tier-1 JSON decode failed for 0x${frameType.toString(16).padStart(2, "0")}: ${String(err)}`);
30
+ }
31
+ }
32
+ }
33
+ // ── Tier-2 MsgPack codec ──────────────────────────────────────────────────────
34
+ export class Tier2MsgPackCodec {
35
+ encode(frame) {
36
+ try {
37
+ return msgpack.encode(frame.toDict());
38
+ }
39
+ catch (err) {
40
+ throw new NpsCodecError(`Tier-2 MsgPack encode failed for 0x${frame.frameType.toString(16).padStart(2, "0")}: ${String(err)}`);
41
+ }
42
+ }
43
+ decode(frameType, payload, registry) {
44
+ const cls = registry.resolve(frameType);
45
+ try {
46
+ const data = msgpack.decode(payload);
47
+ return cls.fromDict(data);
48
+ }
49
+ catch (err) {
50
+ throw new NpsCodecError(`Tier-2 MsgPack decode failed for 0x${frameType.toString(16).padStart(2, "0")}: ${String(err)}`);
51
+ }
52
+ }
53
+ }
54
+ // ── NpsFrameCodec (dispatcher) ────────────────────────────────────────────────
55
+ export class NpsFrameCodec {
56
+ _registry;
57
+ _maxPayload;
58
+ _json = new Tier1JsonCodec();
59
+ _msgpack = new Tier2MsgPackCodec();
60
+ constructor(registry, options = {}) {
61
+ this._registry = registry;
62
+ this._maxPayload = options.maxPayload ?? DEFAULT_MAX_PAYLOAD;
63
+ }
64
+ // ── Encode ────────────────────────────────────────────────────────────────
65
+ encode(frame, options = {}) {
66
+ const tier = options.overrideTier ?? frame.preferredTier;
67
+ const tierCodec = this._selectCodec(tier);
68
+ let payload;
69
+ try {
70
+ payload = tierCodec.encode(frame);
71
+ }
72
+ catch (err) {
73
+ if (err instanceof NpsCodecError)
74
+ throw err;
75
+ throw new NpsCodecError(`Encode failed for 0x${frame.frameType.toString(16)}.`);
76
+ }
77
+ if (payload.length > this._maxPayload) {
78
+ throw new NpsCodecError(`Encoded payload for 0x${frame.frameType.toString(16).padStart(2, "0")} exceeds max_frame_payload` +
79
+ ` (${payload.length} bytes > ${this._maxPayload}). Use StreamFrame (0x03) for large payloads.`);
80
+ }
81
+ const useExt = payload.length > DEFAULT_MAX_PAYLOAD;
82
+ let flags = this._buildFlags(frame, tier);
83
+ if (useExt)
84
+ flags |= FrameFlags.EXT;
85
+ const header = new FrameHeader(frame.frameType, flags, payload.length);
86
+ const headerBytes = header.toBytes();
87
+ const wire = new Uint8Array(headerBytes.length + payload.length);
88
+ wire.set(headerBytes, 0);
89
+ wire.set(payload, headerBytes.length);
90
+ return wire;
91
+ }
92
+ // ── Decode ────────────────────────────────────────────────────────────────
93
+ decode(wire) {
94
+ const header = FrameHeader.parse(wire);
95
+ const payload = wire.slice(header.headerSize, header.headerSize + header.payloadLength);
96
+ const codec = this._selectCodec(header.encodingTier);
97
+ return codec.decode(header.frameType, payload, this._registry);
98
+ }
99
+ static peekHeader(wire) {
100
+ return FrameHeader.parse(wire);
101
+ }
102
+ // ── Private ───────────────────────────────────────────────────────────────
103
+ _buildFlags(frame, tier) {
104
+ let flags = tier === EncodingTier.JSON ? FrameFlags.TIER1_JSON : FrameFlags.TIER2_MSGPACK;
105
+ const isStreamFrame = "isLast" in frame;
106
+ const isFinal = !isStreamFrame || frame.isLast;
107
+ if (isFinal)
108
+ flags |= FrameFlags.FINAL;
109
+ return flags;
110
+ }
111
+ _selectCodec(tier) {
112
+ if (tier === EncodingTier.JSON)
113
+ return this._json;
114
+ if (tier === EncodingTier.MSGPACK)
115
+ return this._msgpack;
116
+ throw new NpsCodecError(`Unsupported encoding tier: 0x${tier.toString(16).padStart(2, "0")}.`);
117
+ }
118
+ }
119
+ //# sourceMappingURL=codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.js","sourceRoot":"","sources":["../../src/core/codec.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;AAEtC;;;GAGG;AAEH,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,WAAW,GAEZ,MAAM,aAAa,CAAC;AAWrB,iFAAiF;AAEjF,MAAM,OAAO,cAAc;IACzB,MAAM,CAAC,KAAe;QACpB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;YAC5C,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,aAAa,CACrB,mCAAmC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,EAAE,CACnG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,CAAC,SAAoB,EAAE,OAAmB,EAAE,QAAuB;QACvE,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;YACzD,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,aAAa,CACrB,mCAAmC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,EAAE,CAC7F,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AAED,iFAAiF;AAEjF,MAAM,OAAO,iBAAiB;IAC5B,MAAM,CAAC,KAAe;QACpB,IAAI,CAAC;YACH,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,aAAa,CACrB,sCAAsC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,EAAE,CACtG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,CAAC,SAAoB,EAAE,OAAmB,EAAE,QAAuB;QACvE,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAA4B,CAAC;YAChE,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,aAAa,CACrB,sCAAsC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,EAAE,CAChG,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AAED,iFAAiF;AAEjF,MAAM,OAAO,aAAa;IACP,SAAS,CAAgB;IACzB,WAAW,CAAS;IACpB,KAAK,GAAM,IAAI,cAAc,EAAE,CAAC;IAChC,QAAQ,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAEpD,YAAY,QAAuB,EAAE,UAAmC,EAAE;QACxE,IAAI,CAAC,SAAS,GAAK,QAAQ,CAAC;QAC5B,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;IAC/D,CAAC;IAED,6EAA6E;IAE7E,MAAM,CAAC,KAAe,EAAE,UAA2C,EAAE;QACnE,MAAM,IAAI,GAAM,OAAO,CAAC,YAAY,IAAI,KAAK,CAAC,aAAa,CAAC;QAC5D,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAE1C,IAAI,OAAmB,CAAC;QACxB,IAAI,CAAC;YACH,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,aAAa;gBAAE,MAAM,GAAG,CAAC;YAC5C,MAAM,IAAI,aAAa,CAAC,uBAAuB,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;QAClF,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YACtC,MAAM,IAAI,aAAa,CACrB,yBAAyB,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,4BAA4B;gBAClG,KAAK,OAAO,CAAC,MAAM,YAAY,IAAI,CAAC,WAAW,+CAA+C,CAC/F,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,mBAAmB,CAAC;QACpD,IAAI,KAAK,GAAM,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC7C,IAAI,MAAM;YAAE,KAAK,IAAI,UAAU,CAAC,GAAG,CAAC;QAEpC,MAAM,MAAM,GAAO,IAAI,WAAW,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3E,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;QACrC,MAAM,IAAI,GAAS,IAAI,UAAU,CAAC,WAAW,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QACvE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6EAA6E;IAE7E,MAAM,CAAC,IAAgB;QACrB,MAAM,MAAM,GAAI,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;QACxF,MAAM,KAAK,GAAK,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACvD,OAAO,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,IAAgB;QAChC,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,6EAA6E;IAErE,WAAW,CAAC,KAAe,EAAE,IAAkB;QACrD,IAAI,KAAK,GAAG,IAAI,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC;QAE1F,MAAM,aAAa,GAAG,QAAQ,IAAI,KAAK,CAAC;QACxC,MAAM,OAAO,GAAS,CAAC,aAAa,IAAK,KAA6B,CAAC,MAAM,CAAC;QAC9E,IAAI,OAAO;YAAE,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;QAEvC,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,YAAY,CAAC,IAAkB;QACrC,IAAI,IAAI,KAAK,YAAY,CAAC,IAAI;YAAK,OAAO,IAAI,CAAC,KAAK,CAAC;QACrD,IAAI,IAAI,KAAK,YAAY,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC,QAAQ,CAAC;QACxD,MAAM,IAAI,aAAa,CAAC,gCAAiC,IAAe,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7G,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 LabAcacia / INNO LOTUS PTY LTD
3
+ export * from "./ncp-codec.js";
4
+ export { encodeJson, decodeJson } from "./tier1-json-codec.js";
5
+ export { encodeMsgPack, decodeMsgPack } from "./tier2-msgpack-codec.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/codecs/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,oDAAoD;AACpD,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC"}