@labacacia/nps-sdk 1.0.0-alpha.3 → 1.0.0-alpha.4
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.
- package/CHANGELOG.cn.md +53 -0
- package/CHANGELOG.md +62 -0
- package/README.cn.md +8 -2
- package/README.md +8 -2
- package/dist/core/anchor-cache.js +104 -0
- package/dist/core/anchor-cache.js.map +1 -0
- package/dist/core/cache.js +80 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/canonical-json.js +44 -0
- package/dist/core/canonical-json.js.map +1 -0
- package/dist/core/codec.js +119 -0
- package/dist/core/codec.js.map +1 -0
- package/dist/core/codecs/index.js +6 -0
- package/dist/core/codecs/index.js.map +1 -0
- package/dist/core/codecs/ncp-codec.js +93 -0
- package/dist/core/codecs/ncp-codec.js.map +1 -0
- package/dist/core/codecs/tier1-json-codec.js +28 -0
- package/dist/core/codecs/tier1-json-codec.js.map +1 -0
- package/dist/core/codecs/tier2-msgpack-codec.js +26 -0
- package/dist/core/codecs/tier2-msgpack-codec.js.map +1 -0
- package/dist/core/crypto-provider.js +10 -0
- package/dist/core/crypto-provider.js.map +1 -0
- package/dist/core/exceptions.js +52 -0
- package/dist/core/exceptions.js.map +1 -0
- package/dist/core/frame-header.js +185 -0
- package/dist/core/frame-header.js.map +1 -0
- package/dist/core/frame-registry.js +63 -0
- package/dist/core/frame-registry.js.map +1 -0
- package/dist/core/frames.js +154 -0
- package/dist/core/frames.js.map +1 -0
- package/dist/core/index.js +21 -405
- package/dist/core/index.js.map +1 -1
- package/dist/core/registry.js +17 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/core/status-codes.js +38 -0
- package/dist/core/status-codes.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +9 -5
- package/dist/index.js.map +1 -1
- package/dist/ncp/frames/anchor-frame.js +54 -0
- package/dist/ncp/frames/anchor-frame.js.map +1 -0
- package/dist/ncp/frames/caps-frame.js +29 -0
- package/dist/ncp/frames/caps-frame.js.map +1 -0
- package/dist/ncp/frames/diff-frame.js +37 -0
- package/dist/ncp/frames/diff-frame.js.map +1 -0
- package/dist/ncp/frames/error-frame.js +13 -0
- package/dist/ncp/frames/error-frame.js.map +1 -0
- package/dist/ncp/frames/hello-frame.js +25 -0
- package/dist/ncp/frames/hello-frame.js.map +1 -0
- package/dist/ncp/frames/stream-frame.js +18 -0
- package/dist/ncp/frames/stream-frame.js.map +1 -0
- package/dist/ncp/frames.js +192 -0
- package/dist/ncp/frames.js.map +1 -0
- package/dist/ncp/handshake.js +80 -0
- package/dist/ncp/handshake.js.map +1 -0
- package/dist/ncp/index.d.ts +1 -0
- package/dist/ncp/index.d.ts.map +1 -1
- package/dist/ncp/index.js +13 -368
- package/dist/ncp/index.js.map +1 -1
- package/dist/ncp/ncp-error-codes.d.ts +1 -0
- package/dist/ncp/ncp-error-codes.d.ts.map +1 -1
- package/dist/ncp/ncp-error-codes.js +34 -0
- package/dist/ncp/ncp-error-codes.js.map +1 -0
- package/dist/ncp/ncp-patch-format.js +13 -0
- package/dist/ncp/ncp-patch-format.js.map +1 -0
- package/dist/ncp/preamble.d.ts +47 -0
- package/dist/ncp/preamble.d.ts.map +1 -0
- package/dist/ncp/preamble.js +74 -0
- package/dist/ncp/preamble.js.map +1 -0
- package/dist/ncp/registry.js +13 -0
- package/dist/ncp/registry.js.map +1 -0
- package/dist/ncp/stream-manager.js +163 -0
- package/dist/ncp/stream-manager.js.map +1 -0
- package/dist/ndp/frames.js +87 -0
- package/dist/ndp/frames.js.map +1 -0
- package/dist/ndp/index.js +6 -223
- package/dist/ndp/index.js.map +1 -1
- package/dist/ndp/ndp-registry.js +79 -0
- package/dist/ndp/ndp-registry.js.map +1 -0
- package/dist/ndp/registry.js +10 -0
- package/dist/ndp/registry.js.map +1 -0
- package/dist/ndp/validator.js +48 -0
- package/dist/ndp/validator.js.map +1 -0
- package/dist/nip/acme/client.d.ts +31 -0
- package/dist/nip/acme/client.d.ts.map +1 -0
- package/dist/nip/acme/client.js +136 -0
- package/dist/nip/acme/client.js.map +1 -0
- package/dist/nip/acme/index.d.ts +6 -0
- package/dist/nip/acme/index.d.ts.map +1 -0
- package/dist/nip/acme/index.js +8 -0
- package/dist/nip/acme/index.js.map +1 -0
- package/dist/nip/acme/jws.d.ts +31 -0
- package/dist/nip/acme/jws.d.ts.map +1 -0
- package/dist/nip/acme/jws.js +76 -0
- package/dist/nip/acme/jws.js.map +1 -0
- package/dist/nip/acme/messages.d.ts +71 -0
- package/dist/nip/acme/messages.d.ts.map +1 -0
- package/dist/nip/acme/messages.js +4 -0
- package/dist/nip/acme/messages.js.map +1 -0
- package/dist/nip/acme/server.d.ts +41 -0
- package/dist/nip/acme/server.d.ts.map +1 -0
- package/dist/nip/acme/server.js +458 -0
- package/dist/nip/acme/server.js.map +1 -0
- package/dist/nip/acme/wire.d.ts +19 -0
- package/dist/nip/acme/wire.d.ts.map +1 -0
- package/dist/nip/acme/wire.js +21 -0
- package/dist/nip/acme/wire.js.map +1 -0
- package/dist/nip/assurance-level.d.ts +14 -0
- package/dist/nip/assurance-level.d.ts.map +1 -0
- package/dist/nip/assurance-level.js +33 -0
- package/dist/nip/assurance-level.js.map +1 -0
- package/dist/nip/cert-format.d.ts +5 -0
- package/dist/nip/cert-format.d.ts.map +1 -0
- package/dist/nip/cert-format.js +6 -0
- package/dist/nip/cert-format.js.map +1 -0
- package/dist/nip/error-codes.d.ts +23 -0
- package/dist/nip/error-codes.d.ts.map +1 -0
- package/dist/nip/error-codes.js +30 -0
- package/dist/nip/error-codes.js.map +1 -0
- package/dist/nip/frames.d.ts +10 -1
- package/dist/nip/frames.d.ts.map +1 -1
- package/dist/nip/frames.js +106 -0
- package/dist/nip/frames.js.map +1 -0
- package/dist/nip/identity.js +94 -0
- package/dist/nip/identity.js.map +1 -0
- package/dist/nip/index.d.ts +6 -0
- package/dist/nip/index.d.ts.map +1 -1
- package/dist/nip/index.js +12 -187
- package/dist/nip/index.js.map +1 -1
- package/dist/nip/registry.js +10 -0
- package/dist/nip/registry.js.map +1 -0
- package/dist/nip/verifier.d.ts +23 -0
- package/dist/nip/verifier.d.ts.map +1 -0
- package/dist/nip/verifier.js +90 -0
- package/dist/nip/verifier.js.map +1 -0
- package/dist/nip/x509/builder.d.ts +35 -0
- package/dist/nip/x509/builder.d.ts.map +1 -0
- package/dist/nip/x509/builder.js +59 -0
- package/dist/nip/x509/builder.js.map +1 -0
- package/dist/nip/x509/index.d.ts +4 -0
- package/dist/nip/x509/index.d.ts.map +1 -0
- package/dist/nip/x509/index.js +6 -0
- package/dist/nip/x509/index.js.map +1 -0
- package/dist/nip/x509/oids.d.ts +17 -0
- package/dist/nip/x509/oids.d.ts.map +1 -0
- package/dist/nip/x509/oids.js +23 -0
- package/dist/nip/x509/oids.js.map +1 -0
- package/dist/nip/x509/verifier.d.ts +26 -0
- package/dist/nip/x509/verifier.d.ts.map +1 -0
- package/dist/nip/x509/verifier.js +171 -0
- package/dist/nip/x509/verifier.js.map +1 -0
- package/dist/nop/client.js +90 -0
- package/dist/nop/client.js.map +1 -0
- package/dist/nop/frames.js +148 -0
- package/dist/nop/frames.js.map +1 -0
- package/dist/nop/index.js +6 -789
- package/dist/nop/index.js.map +1 -1
- package/dist/nop/models.js +50 -0
- package/dist/nop/models.js.map +1 -0
- package/dist/nop/nop-types.js +44 -0
- package/dist/nop/nop-types.js.map +1 -0
- package/dist/nop/registry.js +11 -0
- package/dist/nop/registry.js.map +1 -0
- package/dist/nwp/client.js +101 -0
- package/dist/nwp/client.js.map +1 -0
- package/dist/nwp/frames.js +81 -0
- package/dist/nwp/frames.js.map +1 -0
- package/dist/nwp/index.js +5 -693
- package/dist/nwp/index.js.map +1 -1
- package/dist/nwp/registry.js +9 -0
- package/dist/nwp/registry.js.map +1 -0
- package/dist/setup.js +29 -0
- package/dist/setup.js.map +1 -0
- package/package.json +2 -1
- package/src/index.ts +1 -1
- package/src/ncp/index.ts +1 -0
- package/src/ncp/ncp-error-codes.ts +2 -0
- package/src/ncp/preamble.ts +79 -0
- package/src/nip/acme/client.ts +185 -0
- package/src/nip/acme/index.ts +8 -0
- package/src/nip/acme/jws.ts +109 -0
- package/src/nip/acme/messages.ts +85 -0
- package/src/nip/acme/server.ts +480 -0
- package/src/nip/acme/wire.ts +24 -0
- package/src/nip/assurance-level.ts +35 -0
- package/src/nip/cert-format.ts +9 -0
- package/src/nip/error-codes.ts +36 -0
- package/src/nip/frames.ts +35 -3
- package/src/nip/index.ts +8 -0
- package/src/nip/verifier.ts +122 -0
- package/src/nip/x509/builder.ts +91 -0
- package/src/nip/x509/index.ts +6 -0
- package/src/nip/x509/oids.ts +28 -0
- package/src/nip/x509/verifier.ts +214 -0
- package/tests/_rfc0002-keys.ts +57 -0
- package/tests/ncp/preamble.test.ts +93 -0
- package/tests/nip-acme-agent01.test.ts +192 -0
- package/tests/nip-x509.test.ts +280 -0
- package/dist/core/index.cjs +0 -452
- package/dist/core/index.cjs.map +0 -1
- package/dist/index.cjs +0 -8
- package/dist/index.cjs.map +0 -1
- package/dist/ncp/index.cjs +0 -388
- package/dist/ncp/index.cjs.map +0 -1
- package/dist/ndp/index.cjs +0 -252
- package/dist/ndp/index.cjs.map +0 -1
- package/dist/nip/index.cjs +0 -214
- package/dist/nip/index.cjs.map +0 -1
- package/dist/nop/index.cjs +0 -823
- package/dist/nop/index.cjs.map +0 -1
- package/dist/nwp/index.cjs +0 -720
- package/dist/nwp/index.cjs.map +0 -1
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) 2026 LabAcacia / INNO LOTUS PTY LTD
|
|
3
|
+
//
|
|
4
|
+
// NCP Codec — Top-level encode/decode dispatcher
|
|
5
|
+
// Routes to Tier-1 JSON or Tier-2 MsgPack based on frame header flags.
|
|
6
|
+
import { parseFrameHeader, writeFrameHeader, buildFlags, EncodingTier, NcpError, DEFAULT_MAX_PAYLOAD, } from "../frame-header.js";
|
|
7
|
+
import { encodeJson, decodeJson } from "./tier1-json-codec.js";
|
|
8
|
+
import { encodeMsgPack, decodeMsgPack } from "./tier2-msgpack-codec.js";
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Decode
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/**
|
|
13
|
+
* Decode a complete NCP frame from a buffer.
|
|
14
|
+
*
|
|
15
|
+
* @returns Decoded header + payload + bytes consumed.
|
|
16
|
+
* @throws {NcpError} NCP-ENCODING-UNSUPPORTED for reserved tiers.
|
|
17
|
+
* @throws {NcpError} NCP-FRAME-PAYLOAD-TOO-LARGE if payload exceeds max.
|
|
18
|
+
* @throws {NcpError} NCP-FRAME-INCOMPLETE if buffer doesn't have enough data.
|
|
19
|
+
*/
|
|
20
|
+
export function decodeFrame(buffer, options) {
|
|
21
|
+
const header = parseFrameHeader(buffer);
|
|
22
|
+
const maxPayload = options?.maxFramePayload ?? DEFAULT_MAX_PAYLOAD;
|
|
23
|
+
// NCP-F-09: Validate against negotiated max_frame_payload
|
|
24
|
+
if (header.payloadLength > maxPayload) {
|
|
25
|
+
throw new NcpError("NCP-FRAME-PAYLOAD-TOO-LARGE", `Payload ${header.payloadLength} exceeds max_frame_payload ${maxPayload}`);
|
|
26
|
+
}
|
|
27
|
+
const totalSize = header.headerSize + header.payloadLength;
|
|
28
|
+
// NCP-F-05: Buffer underrun — not enough data for payload
|
|
29
|
+
if (buffer.length < totalSize) {
|
|
30
|
+
throw new NcpError("NCP-FRAME-INCOMPLETE", `Buffer has ${buffer.length} bytes but frame needs ${totalSize}`);
|
|
31
|
+
}
|
|
32
|
+
// Extract payload bytes
|
|
33
|
+
const payloadBytes = buffer.subarray(header.headerSize, header.headerSize + header.payloadLength);
|
|
34
|
+
// Route to codec by tier
|
|
35
|
+
let payload;
|
|
36
|
+
switch (header.tier) {
|
|
37
|
+
case EncodingTier.Json:
|
|
38
|
+
payload = decodeJson(payloadBytes);
|
|
39
|
+
break;
|
|
40
|
+
case EncodingTier.MsgPack:
|
|
41
|
+
payload = decodeMsgPack(payloadBytes);
|
|
42
|
+
break;
|
|
43
|
+
default:
|
|
44
|
+
// NCP-E-05: Reserved tiers (0x02, 0x03)
|
|
45
|
+
throw new NcpError("NCP-ENCODING-UNSUPPORTED", `Unsupported encoding tier: 0x${header.tier.toString(16).padStart(2, "0")}`);
|
|
46
|
+
}
|
|
47
|
+
return { header, payload, bytesConsumed: totalSize };
|
|
48
|
+
}
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Encode
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
/**
|
|
53
|
+
* Encode a payload into a complete NCP frame (header + payload bytes).
|
|
54
|
+
*/
|
|
55
|
+
export function encodeFrame(payload, options) {
|
|
56
|
+
const tier = options.tier ?? EncodingTier.Json;
|
|
57
|
+
// Encode payload
|
|
58
|
+
let payloadBytes;
|
|
59
|
+
switch (tier) {
|
|
60
|
+
case EncodingTier.Json:
|
|
61
|
+
payloadBytes = encodeJson(payload);
|
|
62
|
+
break;
|
|
63
|
+
case EncodingTier.MsgPack:
|
|
64
|
+
payloadBytes = encodeMsgPack(payload);
|
|
65
|
+
break;
|
|
66
|
+
default:
|
|
67
|
+
throw new NcpError("NCP-ENCODING-UNSUPPORTED", `Unsupported encoding tier for encode: ${tier}`);
|
|
68
|
+
}
|
|
69
|
+
// Determine if extended header is needed
|
|
70
|
+
const needsExtended = options.extended || payloadBytes.length > DEFAULT_MAX_PAYLOAD;
|
|
71
|
+
const flags = buildFlags({
|
|
72
|
+
tier,
|
|
73
|
+
final: options.final,
|
|
74
|
+
encrypted: options.encrypted,
|
|
75
|
+
extended: needsExtended,
|
|
76
|
+
});
|
|
77
|
+
const header = {
|
|
78
|
+
frameType: options.frameType,
|
|
79
|
+
flags,
|
|
80
|
+
payloadLength: payloadBytes.length,
|
|
81
|
+
tier,
|
|
82
|
+
isFinal: options.final ?? false,
|
|
83
|
+
isEncrypted: options.encrypted ?? false,
|
|
84
|
+
isExtended: needsExtended,
|
|
85
|
+
headerSize: needsExtended ? 8 : 4,
|
|
86
|
+
};
|
|
87
|
+
// Write frame
|
|
88
|
+
const frame = new Uint8Array(header.headerSize + payloadBytes.length);
|
|
89
|
+
writeFrameHeader(header, frame);
|
|
90
|
+
frame.set(payloadBytes, header.headerSize);
|
|
91
|
+
return frame;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=ncp-codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ncp-codec.js","sourceRoot":"","sources":["../../../src/core/codecs/ncp-codec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) 2026 LabAcacia / INNO LOTUS PTY LTD
|
|
3
|
+
//
|
|
4
|
+
// Tier-1 JSON Codec — UTF-8 JSON encode/decode
|
|
5
|
+
// NPS-1 §8
|
|
6
|
+
import { NcpError } from "../frame-header.js";
|
|
7
|
+
const encoder = new TextEncoder();
|
|
8
|
+
const decoder = new TextDecoder();
|
|
9
|
+
/**
|
|
10
|
+
* Encode a frame payload to Tier-1 JSON bytes.
|
|
11
|
+
*/
|
|
12
|
+
export function encodeJson(payload) {
|
|
13
|
+
return encoder.encode(JSON.stringify(payload));
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Decode Tier-1 JSON bytes to a parsed object.
|
|
17
|
+
* @throws {NcpError} NPS-CLIENT-BAD-FRAME on malformed JSON.
|
|
18
|
+
*/
|
|
19
|
+
export function decodeJson(bytes) {
|
|
20
|
+
const text = decoder.decode(bytes);
|
|
21
|
+
try {
|
|
22
|
+
return JSON.parse(text);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
throw new NcpError("NPS-CLIENT-BAD-FRAME", "Malformed JSON payload");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=tier1-json-codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tier1-json-codec.js","sourceRoot":"","sources":["../../../src/core/codecs/tier1-json-codec.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,oDAAoD;AACpD,EAAE;AACF,+CAA+C;AAC/C,WAAW;AAEX,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAClC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,OAAgB;IACzC,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,KAAiB;IAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,QAAQ,CAChB,sBAAsB,EACtB,wBAAwB,CACzB,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) 2026 LabAcacia / INNO LOTUS PTY LTD
|
|
3
|
+
//
|
|
4
|
+
// Tier-2 MsgPack Codec — Binary encode/decode
|
|
5
|
+
// NPS-1 §8
|
|
6
|
+
import { encode, decode } from "@msgpack/msgpack";
|
|
7
|
+
import { NcpError } from "../frame-header.js";
|
|
8
|
+
/**
|
|
9
|
+
* Encode a frame payload to Tier-2 MsgPack bytes.
|
|
10
|
+
*/
|
|
11
|
+
export function encodeMsgPack(payload) {
|
|
12
|
+
return encode(payload);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Decode Tier-2 MsgPack bytes to a parsed object.
|
|
16
|
+
* @throws {NcpError} NPS-CLIENT-BAD-FRAME on malformed MsgPack.
|
|
17
|
+
*/
|
|
18
|
+
export function decodeMsgPack(bytes) {
|
|
19
|
+
try {
|
|
20
|
+
return decode(bytes);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
throw new NcpError("NPS-CLIENT-BAD-FRAME", "Malformed MsgPack payload");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=tier2-msgpack-codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tier2-msgpack-codec.js","sourceRoot":"","sources":["../../../src/core/codecs/tier2-msgpack-codec.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,oDAAoD;AACpD,EAAE;AACF,8CAA8C;AAC9C,WAAW;AAEX,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC7C,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,KAAK,CAAY,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,QAAQ,CAChB,sBAAsB,EACtB,2BAA2B,CAC5B,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) 2026 LabAcacia / INNO LOTUS PTY LTD
|
|
3
|
+
//
|
|
4
|
+
// CryptoProvider interface — async crypto abstraction for Node + browser.
|
|
5
|
+
// NPS-3 §10 / Q10 resolution in nps-ts-sdk-step7-plan.
|
|
6
|
+
//
|
|
7
|
+
// Implementations (NodeCryptoProvider, WebCryptoProvider) land at P3
|
|
8
|
+
// alongside NIP tests. This file is structural scaffold only.
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=crypto-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto-provider.js","sourceRoot":"","sources":["../../src/core/crypto-provider.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,oDAAoD;AACpD,EAAE;AACF,0EAA0E;AAC1E,uDAAuD;AACvD,EAAE;AACF,qEAAqE;AACrE,8DAA8D"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) 2026 LabAcacia / INNO LOTUS PTY LTD
|
|
3
|
+
//
|
|
4
|
+
// NPS exception hierarchy — ported from nps_sdk/core/exceptions.py
|
|
5
|
+
// NPS-1 §6
|
|
6
|
+
/** Base class for all NPS SDK errors. */
|
|
7
|
+
export class NpsError extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "NpsError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** Frame parse or structural error. */
|
|
14
|
+
export class NpsFrameError extends NpsError {
|
|
15
|
+
constructor(message) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = "NpsFrameError";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Encode or decode error. */
|
|
21
|
+
export class NpsCodecError extends NpsError {
|
|
22
|
+
constructor(message) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = "NpsCodecError";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Anchor cache miss — requested anchor ID not found. */
|
|
28
|
+
export class NpsAnchorNotFoundError extends NpsError {
|
|
29
|
+
anchorId;
|
|
30
|
+
constructor(anchorId, message) {
|
|
31
|
+
super(message ?? `Anchor not found: ${anchorId}`);
|
|
32
|
+
this.name = "NpsAnchorNotFoundError";
|
|
33
|
+
this.anchorId = anchorId;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Anchor ID collision — same ID but different schema content. */
|
|
37
|
+
export class NpsAnchorPoisonError extends NpsError {
|
|
38
|
+
anchorId;
|
|
39
|
+
constructor(anchorId, message) {
|
|
40
|
+
super(message ?? `Anchor poison detected: ${anchorId}`);
|
|
41
|
+
this.name = "NpsAnchorPoisonError";
|
|
42
|
+
this.anchorId = anchorId;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Stream-level error (sequence gap, unknown stream ID, etc.). */
|
|
46
|
+
export class NpsStreamError extends NpsError {
|
|
47
|
+
constructor(message) {
|
|
48
|
+
super(message);
|
|
49
|
+
this.name = "NpsStreamError";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=exceptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exceptions.js","sourceRoot":"","sources":["../../src/core/exceptions.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,oDAAoD;AACpD,EAAE;AACF,mEAAmE;AACnE,WAAW;AAEX,yCAAyC;AACzC,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,uCAAuC;AACvC,MAAM,OAAO,aAAc,SAAQ,QAAQ;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,8BAA8B;AAC9B,MAAM,OAAO,aAAc,SAAQ,QAAQ;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,yDAAyD;AACzD,MAAM,OAAO,sBAAuB,SAAQ,QAAQ;IACzC,QAAQ,CAAS;IAC1B,YAAY,QAAgB,EAAE,OAAgB;QAC5C,KAAK,CAAC,OAAO,IAAI,qBAAqB,QAAQ,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF;AAED,kEAAkE;AAClE,MAAM,OAAO,oBAAqB,SAAQ,QAAQ;IACvC,QAAQ,CAAS;IAC1B,YAAY,QAAgB,EAAE,OAAgB;QAC5C,KAAK,CAAC,OAAO,IAAI,2BAA2B,QAAQ,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF;AAED,kEAAkE;AAClE,MAAM,OAAO,cAAe,SAAQ,QAAQ;IAC1C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) 2026 LabAcacia / INNO LOTUS PTY LTD
|
|
3
|
+
//
|
|
4
|
+
// NCP Frame Header — Binary parse/write for NPS wire format
|
|
5
|
+
// NPS-1 Neural Communication Protocol §3.1, §3.2
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Enums
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
/** Wire encoding tier (NPS-1 §3.2, flags bits 0-1). */
|
|
10
|
+
export var EncodingTier;
|
|
11
|
+
(function (EncodingTier) {
|
|
12
|
+
/** Tier-1: UTF-8 JSON — development & compatibility. */
|
|
13
|
+
EncodingTier[EncodingTier["Json"] = 0] = "Json";
|
|
14
|
+
/** Tier-2: MessagePack binary — production (~60% compression). */
|
|
15
|
+
EncodingTier[EncodingTier["MsgPack"] = 1] = "MsgPack";
|
|
16
|
+
// 0x02 = Reserved
|
|
17
|
+
// 0x03 = Reserved
|
|
18
|
+
})(EncodingTier || (EncodingTier = {}));
|
|
19
|
+
/** Unified frame type namespace for the full NPS suite (NPS-0 §9). */
|
|
20
|
+
export var FrameType;
|
|
21
|
+
(function (FrameType) {
|
|
22
|
+
// NCP 0x01–0x0F
|
|
23
|
+
FrameType[FrameType["Anchor"] = 1] = "Anchor";
|
|
24
|
+
FrameType[FrameType["Diff"] = 2] = "Diff";
|
|
25
|
+
FrameType[FrameType["Stream"] = 3] = "Stream";
|
|
26
|
+
FrameType[FrameType["Caps"] = 4] = "Caps";
|
|
27
|
+
FrameType[FrameType["Align"] = 5] = "Align";
|
|
28
|
+
FrameType[FrameType["Hello"] = 6] = "Hello";
|
|
29
|
+
// NWP 0x10–0x1F
|
|
30
|
+
FrameType[FrameType["Query"] = 16] = "Query";
|
|
31
|
+
FrameType[FrameType["Action"] = 17] = "Action";
|
|
32
|
+
FrameType[FrameType["Subscribe"] = 18] = "Subscribe";
|
|
33
|
+
// NIP 0x20–0x2F
|
|
34
|
+
FrameType[FrameType["Ident"] = 32] = "Ident";
|
|
35
|
+
FrameType[FrameType["Trust"] = 33] = "Trust";
|
|
36
|
+
FrameType[FrameType["Revoke"] = 34] = "Revoke";
|
|
37
|
+
// NDP 0x30–0x3F
|
|
38
|
+
FrameType[FrameType["Announce"] = 48] = "Announce";
|
|
39
|
+
FrameType[FrameType["Resolve"] = 49] = "Resolve";
|
|
40
|
+
FrameType[FrameType["Graph"] = 50] = "Graph";
|
|
41
|
+
// NOP 0x40–0x4F
|
|
42
|
+
FrameType[FrameType["Task"] = 64] = "Task";
|
|
43
|
+
FrameType[FrameType["Delegate"] = 65] = "Delegate";
|
|
44
|
+
FrameType[FrameType["Sync"] = 66] = "Sync";
|
|
45
|
+
FrameType[FrameType["AlignStream"] = 67] = "AlignStream";
|
|
46
|
+
// System 0xF0–0xFF
|
|
47
|
+
FrameType[FrameType["Error"] = 254] = "Error";
|
|
48
|
+
})(FrameType || (FrameType = {}));
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Constants
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
/** Default (compact) header size in bytes. */
|
|
53
|
+
export const DEFAULT_HEADER_SIZE = 4;
|
|
54
|
+
/** Extended header size in bytes (EXT=1). */
|
|
55
|
+
export const EXTENDED_HEADER_SIZE = 8;
|
|
56
|
+
/** Maximum payload in default mode (64 KiB − 1). */
|
|
57
|
+
export const DEFAULT_MAX_PAYLOAD = 0xffff;
|
|
58
|
+
/** Maximum payload in extended mode (4 GiB − 1). */
|
|
59
|
+
export const EXTENDED_MAX_PAYLOAD = 0xffffffff;
|
|
60
|
+
// Flag bit positions (NPS-1 §3.2)
|
|
61
|
+
const TIER_MASK = 0x03; // bits 0-1
|
|
62
|
+
const FINAL_BIT = 0x04; // bit 2
|
|
63
|
+
const ENC_BIT = 0x08; // bit 3
|
|
64
|
+
const RESERVED_MASK = 0x70; // bits 4-6
|
|
65
|
+
const EXT_BIT = 0x80; // bit 7
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// Error
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
/** NCP protocol error with machine-readable error code. */
|
|
70
|
+
export class NcpError extends Error {
|
|
71
|
+
code;
|
|
72
|
+
// `code` accepts NcpErrorCode constants (preferred) as well as NPS status
|
|
73
|
+
// strings that are not NCP-prefixed (e.g. "NPS-CLIENT-CONFLICT") for cases
|
|
74
|
+
// where the spec delegates to NPS-level codes without assigning an NCP code.
|
|
75
|
+
constructor(code, message) {
|
|
76
|
+
super(message);
|
|
77
|
+
this.code = code;
|
|
78
|
+
this.name = "NcpError";
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// Parse
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
/**
|
|
85
|
+
* Parse a frame header from the start of the buffer.
|
|
86
|
+
* Reads 2 bytes first to determine EXT, then reads remaining bytes.
|
|
87
|
+
*
|
|
88
|
+
* @throws {NcpError} NCP-FRAME-FLAGS-INVALID if reserved bits 4-6 are non-zero.
|
|
89
|
+
* @throws {NcpError} NCP-FRAME-PARSE-ERROR if buffer is too small.
|
|
90
|
+
* @throws {NcpError} NCP-FRAME-PAYLOAD-TOO-LARGE if opts.max_frame_payload is set and exceeded.
|
|
91
|
+
*/
|
|
92
|
+
export function parseFrameHeader(buffer, opts) {
|
|
93
|
+
if (buffer.length < 2) {
|
|
94
|
+
throw new NcpError("NCP-FRAME-PARSE-ERROR", `Buffer too small to read frame type and flags: need >= 2 bytes, got ${buffer.length}`);
|
|
95
|
+
}
|
|
96
|
+
const frameType = buffer[0];
|
|
97
|
+
const flags = buffer[1];
|
|
98
|
+
// Validate reserved bits (NPS-1 §3.2: bits 4-6 MUST be 0)
|
|
99
|
+
if ((flags & RESERVED_MASK) !== 0) {
|
|
100
|
+
throw new NcpError("NCP-FRAME-FLAGS-INVALID", "Reserved flag bits 4-6 must be zero");
|
|
101
|
+
}
|
|
102
|
+
const isExtended = (flags & EXT_BIT) !== 0;
|
|
103
|
+
if (isExtended) {
|
|
104
|
+
if (buffer.length < EXTENDED_HEADER_SIZE) {
|
|
105
|
+
throw new NcpError("NCP-FRAME-PARSE-ERROR", `Buffer too small for extended header: need ${EXTENDED_HEADER_SIZE} bytes, got ${buffer.length}`);
|
|
106
|
+
}
|
|
107
|
+
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
108
|
+
const payloadLength = view.getUint32(2, false); // big-endian
|
|
109
|
+
if (opts?.max_frame_payload !== undefined &&
|
|
110
|
+
payloadLength > opts.max_frame_payload) {
|
|
111
|
+
throw new NcpError("NCP-FRAME-PAYLOAD-TOO-LARGE", `Payload length ${payloadLength} exceeds max_frame_payload ${opts.max_frame_payload}`);
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
frameType,
|
|
115
|
+
flags,
|
|
116
|
+
payloadLength,
|
|
117
|
+
tier: (flags & TIER_MASK),
|
|
118
|
+
isFinal: (flags & FINAL_BIT) !== 0,
|
|
119
|
+
isEncrypted: (flags & ENC_BIT) !== 0,
|
|
120
|
+
isExtended: true,
|
|
121
|
+
headerSize: EXTENDED_HEADER_SIZE,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
// Default 4-byte header
|
|
125
|
+
if (buffer.length < DEFAULT_HEADER_SIZE) {
|
|
126
|
+
throw new NcpError("NCP-FRAME-PARSE-ERROR", `Buffer too small for header: need ${DEFAULT_HEADER_SIZE} bytes, got ${buffer.length}`);
|
|
127
|
+
}
|
|
128
|
+
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
129
|
+
const payloadLength = view.getUint16(2, false); // big-endian
|
|
130
|
+
if (opts?.max_frame_payload !== undefined &&
|
|
131
|
+
payloadLength > opts.max_frame_payload) {
|
|
132
|
+
throw new NcpError("NCP-FRAME-PAYLOAD-TOO-LARGE", `Payload length ${payloadLength} exceeds max_frame_payload ${opts.max_frame_payload}`);
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
frameType,
|
|
136
|
+
flags,
|
|
137
|
+
payloadLength,
|
|
138
|
+
tier: (flags & TIER_MASK),
|
|
139
|
+
isFinal: (flags & FINAL_BIT) !== 0,
|
|
140
|
+
isEncrypted: (flags & ENC_BIT) !== 0,
|
|
141
|
+
isExtended: false,
|
|
142
|
+
headerSize: DEFAULT_HEADER_SIZE,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
// Write
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
/**
|
|
149
|
+
* Write a frame header into the buffer.
|
|
150
|
+
* @returns Number of bytes written (4 or 8).
|
|
151
|
+
* @throws {Error} if buffer is too small.
|
|
152
|
+
*/
|
|
153
|
+
export function writeFrameHeader(header, buffer) {
|
|
154
|
+
const size = header.isExtended ? EXTENDED_HEADER_SIZE : DEFAULT_HEADER_SIZE;
|
|
155
|
+
if (buffer.length < size) {
|
|
156
|
+
throw new Error(`Destination buffer must be at least ${size} bytes, got ${buffer.length}`);
|
|
157
|
+
}
|
|
158
|
+
buffer[0] = header.frameType;
|
|
159
|
+
buffer[1] = header.flags;
|
|
160
|
+
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
161
|
+
if (header.isExtended) {
|
|
162
|
+
view.setUint32(2, header.payloadLength, false); // big-endian
|
|
163
|
+
buffer[6] = 0; // reserved
|
|
164
|
+
buffer[7] = 0; // reserved
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
view.setUint16(2, header.payloadLength, false); // big-endian
|
|
168
|
+
}
|
|
169
|
+
return size;
|
|
170
|
+
}
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
// Helpers
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
/** Build a flags byte from individual options. */
|
|
175
|
+
export function buildFlags(options) {
|
|
176
|
+
let flags = (options.tier ?? EncodingTier.Json) & TIER_MASK;
|
|
177
|
+
if (options.final)
|
|
178
|
+
flags |= FINAL_BIT;
|
|
179
|
+
if (options.encrypted)
|
|
180
|
+
flags |= ENC_BIT;
|
|
181
|
+
if (options.extended)
|
|
182
|
+
flags |= EXT_BIT;
|
|
183
|
+
return flags;
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=frame-header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame-header.js","sourceRoot":"","sources":["../../src/core/frame-header.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,oDAAoD;AACpD,EAAE;AACF,4DAA4D;AAC5D,iDAAiD;AAEjD,8EAA8E;AAC9E,QAAQ;AACR,8EAA8E;AAE9E,uDAAuD;AACvD,MAAM,CAAN,IAAY,YAOX;AAPD,WAAY,YAAY;IACtB,wDAAwD;IACxD,+CAAW,CAAA;IACX,kEAAkE;IAClE,qDAAc,CAAA;IACd,kBAAkB;IAClB,kBAAkB;AACpB,CAAC,EAPW,YAAY,KAAZ,YAAY,QAOvB;AAED,sEAAsE;AACtE,MAAM,CAAN,IAAY,SA2BX;AA3BD,WAAY,SAAS;IACnB,gBAAgB;IAChB,6CAAa,CAAA;IACb,yCAAW,CAAA;IACX,6CAAa,CAAA;IACb,yCAAW,CAAA;IACX,2CAAY,CAAA;IACZ,2CAAY,CAAA;IACZ,gBAAgB;IAChB,4CAAY,CAAA;IACZ,8CAAa,CAAA;IACb,oDAAgB,CAAA;IAChB,gBAAgB;IAChB,4CAAY,CAAA;IACZ,4CAAY,CAAA;IACZ,8CAAa,CAAA;IACb,gBAAgB;IAChB,kDAAe,CAAA;IACf,gDAAc,CAAA;IACd,4CAAY,CAAA;IACZ,gBAAgB;IAChB,0CAAW,CAAA;IACX,kDAAe,CAAA;IACf,0CAAW,CAAA;IACX,wDAAkB,CAAA;IAClB,mBAAmB;IACnB,6CAAY,CAAA;AACd,CAAC,EA3BW,SAAS,KAAT,SAAS,QA2BpB;AAED,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,8CAA8C;AAC9C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC,6CAA6C;AAC7C,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAEtC,oDAAoD;AACpD,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAE1C,oDAAoD;AACpD,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAE/C,kCAAkC;AAClC,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,WAAW;AACnC,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,QAAQ;AAChC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,QAAQ;AAC9B,MAAM,aAAa,GAAG,IAAI,CAAC,CAAC,WAAW;AACvC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,QAAQ;AAE9B,8EAA8E;AAC9E,QAAQ;AACR,8EAA8E;AAE9E,2DAA2D;AAC3D,MAAM,OAAO,QAAS,SAAQ,KAAK;IAKf;IAJlB,0EAA0E;IAC1E,2EAA2E;IAC3E,6EAA6E;IAC7E,YACkB,IAAY,EAC5B,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,SAAI,GAAJ,IAAI,CAAQ;QAI5B,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AA0BD,8EAA8E;AAC9E,QAAQ;AACR,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAkB,EAClB,IAAqC;IAErC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,QAAQ,CAChB,uBAAuB,EACvB,uEAAuE,MAAM,CAAC,MAAM,EAAE,CACvF,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;IAEzB,0DAA0D;IAC1D,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,QAAQ,CAChB,yBAAyB,EACzB,qCAAqC,CACtC,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAE3C,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,MAAM,CAAC,MAAM,GAAG,oBAAoB,EAAE,CAAC;YACzC,MAAM,IAAI,QAAQ,CAChB,uBAAuB,EACvB,8CAA8C,oBAAoB,eAAe,MAAM,CAAC,MAAM,EAAE,CACjG,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,QAAQ,CACvB,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,UAAU,EACjB,MAAM,CAAC,UAAU,CAClB,CAAC;QACF,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa;QAE7D,IACE,IAAI,EAAE,iBAAiB,KAAK,SAAS;YACrC,aAAa,GAAG,IAAI,CAAC,iBAAiB,EACtC,CAAC;YACD,MAAM,IAAI,QAAQ,CAChB,6BAA6B,EAC7B,kBAAkB,aAAa,8BAA8B,IAAI,CAAC,iBAAiB,EAAE,CACtF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,SAAS;YACT,KAAK;YACL,aAAa;YACb,IAAI,EAAE,CAAC,KAAK,GAAG,SAAS,CAAiB;YACzC,OAAO,EAAE,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;YAClC,WAAW,EAAE,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;YACpC,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,oBAAoB;SACjC,CAAC;IACJ,CAAC;IAED,wBAAwB;IACxB,IAAI,MAAM,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;QACxC,MAAM,IAAI,QAAQ,CAChB,uBAAuB,EACvB,qCAAqC,mBAAmB,eAAe,MAAM,CAAC,MAAM,EAAE,CACvF,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,QAAQ,CACvB,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,UAAU,EACjB,MAAM,CAAC,UAAU,CAClB,CAAC;IACF,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa;IAE7D,IACE,IAAI,EAAE,iBAAiB,KAAK,SAAS;QACrC,aAAa,GAAG,IAAI,CAAC,iBAAiB,EACtC,CAAC;QACD,MAAM,IAAI,QAAQ,CAChB,6BAA6B,EAC7B,kBAAkB,aAAa,8BAA8B,IAAI,CAAC,iBAAiB,EAAE,CACtF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,SAAS;QACT,KAAK;QACL,aAAa;QACb,IAAI,EAAE,CAAC,KAAK,GAAG,SAAS,CAAiB;QACzC,OAAO,EAAE,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;QAClC,WAAW,EAAE,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QACpC,UAAU,EAAE,KAAK;QACjB,UAAU,EAAE,mBAAmB;KAChC,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,QAAQ;AACR,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAmB,EACnB,MAAkB;IAElB,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,mBAAmB,CAAC;IAC5E,IAAI,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,uCAAuC,IAAI,eAAe,MAAM,CAAC,MAAM,EAAE,CAC1E,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC;IAC7B,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;IAEzB,MAAM,IAAI,GAAG,IAAI,QAAQ,CACvB,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,UAAU,EACjB,MAAM,CAAC,UAAU,CAClB,CAAC;IAEF,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa;QAC7D,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW;QAC1B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW;IAC5B,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa;IAC/D,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,kDAAkD;AAClD,MAAM,UAAU,UAAU,CAAC,OAK1B;IACC,IAAI,KAAK,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IAC5D,IAAI,OAAO,CAAC,KAAK;QAAE,KAAK,IAAI,SAAS,CAAC;IACtC,IAAI,OAAO,CAAC,SAAS;QAAE,KAAK,IAAI,OAAO,CAAC;IACxC,IAAI,OAAO,CAAC,QAAQ;QAAE,KAAK,IAAI,OAAO,CAAC;IACvC,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) 2026 LabAcacia / INNO LOTUS PTY LTD
|
|
3
|
+
//
|
|
4
|
+
// NCP Frame Registry — Maps frame type bytes to protocol identifiers
|
|
5
|
+
// NPS-0 §9 Unified frame namespace
|
|
6
|
+
import { FrameType, NcpError } from "./frame-header.js";
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Registry
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
/**
|
|
11
|
+
* Maps frame type bytes to metadata.
|
|
12
|
+
* Built once at startup, then read-only.
|
|
13
|
+
*/
|
|
14
|
+
export class FrameRegistry {
|
|
15
|
+
map;
|
|
16
|
+
constructor(entries) {
|
|
17
|
+
this.map = new Map(entries.map((e) => [e.frameType, e]));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolve a frame type byte to its registry entry.
|
|
21
|
+
* @throws {NcpError} NCP-FRAME-UNKNOWN-TYPE if not registered.
|
|
22
|
+
*/
|
|
23
|
+
resolve(frameType) {
|
|
24
|
+
const entry = this.map.get(frameType);
|
|
25
|
+
if (!entry) {
|
|
26
|
+
throw new NcpError("NCP-FRAME-UNKNOWN-TYPE", `No entry registered for frame type 0x${frameType.toString(16).padStart(2, "0")}`);
|
|
27
|
+
}
|
|
28
|
+
return entry;
|
|
29
|
+
}
|
|
30
|
+
/** Check if a frame type is registered. */
|
|
31
|
+
has(frameType) {
|
|
32
|
+
return this.map.has(frameType);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Create a registry pre-populated with all NCP core frames.
|
|
36
|
+
* Upper-layer protocols can extend via the builder.
|
|
37
|
+
*/
|
|
38
|
+
static createDefault() {
|
|
39
|
+
return new FrameRegistryBuilder()
|
|
40
|
+
.add(FrameType.Anchor, "AnchorFrame", "ncp")
|
|
41
|
+
.add(FrameType.Diff, "DiffFrame", "ncp")
|
|
42
|
+
.add(FrameType.Stream, "StreamFrame", "ncp")
|
|
43
|
+
.add(FrameType.Caps, "CapsFrame", "ncp")
|
|
44
|
+
.add(FrameType.Align, "AlignFrame", "ncp") // deprecated
|
|
45
|
+
.add(FrameType.Hello, "HelloFrame", "ncp")
|
|
46
|
+
.add(FrameType.Error, "ErrorFrame", "system")
|
|
47
|
+
.build();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Builder
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
export class FrameRegistryBuilder {
|
|
54
|
+
entries = [];
|
|
55
|
+
add(frameType, name, protocol) {
|
|
56
|
+
this.entries.push({ frameType, name, protocol });
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
build() {
|
|
60
|
+
return new FrameRegistry(this.entries);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=frame-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame-registry.js","sourceRoot":"","sources":["../../src/core/frame-registry.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,oDAAoD;AACpD,EAAE;AACF,qEAAqE;AACrE,mCAAmC;AAEnC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAiBxD,8EAA8E;AAC9E,WAAW;AACX,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,OAAO,aAAa;IACP,GAAG,CAAkC;IAEtD,YAAY,OAA6B;QACvC,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED;;;OAGG;IACH,OAAO,CAAC,SAAiB;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,QAAQ,CAChB,wBAAwB,EACxB,wCAAwC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAClF,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,2CAA2C;IAC3C,GAAG,CAAC,SAAiB;QACnB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACjC,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,aAAa;QAClB,OAAO,IAAI,oBAAoB,EAAE;aAC9B,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,CAAC;aAC3C,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC;aACvC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,CAAC;aAC3C,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC;aACvC,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC,aAAa;aACvD,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,CAAC;aACzC,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,CAAC;aAC5C,KAAK,EAAE,CAAC;IACb,CAAC;CACF;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,MAAM,OAAO,oBAAoB;IACd,OAAO,GAAyB,EAAE,CAAC;IAEpD,GAAG,CAAC,SAAiB,EAAE,IAAY,EAAE,QAAkB;QACrD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK;QACH,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// Copyright 2026 INNO LOTUS PTY LTD
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* NPS wire-level frame primitives: FrameType, FrameFlags, EncodingTier, FrameHeader.
|
|
5
|
+
*/
|
|
6
|
+
import { NpsFrameError } from "./exceptions.js";
|
|
7
|
+
// ── FrameType ────────────────────────────────────────────────────────────────
|
|
8
|
+
/** Unified frame byte namespace for the full NPS suite (NPS-0 §9). */
|
|
9
|
+
export var FrameType;
|
|
10
|
+
(function (FrameType) {
|
|
11
|
+
// NCP 0x01–0x0F
|
|
12
|
+
FrameType[FrameType["ANCHOR"] = 1] = "ANCHOR";
|
|
13
|
+
FrameType[FrameType["DIFF"] = 2] = "DIFF";
|
|
14
|
+
FrameType[FrameType["STREAM"] = 3] = "STREAM";
|
|
15
|
+
FrameType[FrameType["CAPS"] = 4] = "CAPS";
|
|
16
|
+
FrameType[FrameType["ALIGN"] = 5] = "ALIGN";
|
|
17
|
+
FrameType[FrameType["HELLO"] = 6] = "HELLO";
|
|
18
|
+
// NWP 0x10–0x1F
|
|
19
|
+
FrameType[FrameType["QUERY"] = 16] = "QUERY";
|
|
20
|
+
FrameType[FrameType["ACTION"] = 17] = "ACTION";
|
|
21
|
+
// NIP 0x20–0x2F
|
|
22
|
+
FrameType[FrameType["IDENT"] = 32] = "IDENT";
|
|
23
|
+
FrameType[FrameType["TRUST"] = 33] = "TRUST";
|
|
24
|
+
FrameType[FrameType["REVOKE"] = 34] = "REVOKE";
|
|
25
|
+
// NDP 0x30–0x3F
|
|
26
|
+
FrameType[FrameType["ANNOUNCE"] = 48] = "ANNOUNCE";
|
|
27
|
+
FrameType[FrameType["RESOLVE"] = 49] = "RESOLVE";
|
|
28
|
+
FrameType[FrameType["GRAPH"] = 50] = "GRAPH";
|
|
29
|
+
// NOP 0x40–0x4F
|
|
30
|
+
FrameType[FrameType["TASK"] = 64] = "TASK";
|
|
31
|
+
FrameType[FrameType["DELEGATE"] = 65] = "DELEGATE";
|
|
32
|
+
FrameType[FrameType["SYNC"] = 66] = "SYNC";
|
|
33
|
+
FrameType[FrameType["ALIGN_STREAM"] = 67] = "ALIGN_STREAM";
|
|
34
|
+
// Reserved / System 0xF0–0xFF
|
|
35
|
+
FrameType[FrameType["ERROR"] = 254] = "ERROR";
|
|
36
|
+
})(FrameType || (FrameType = {}));
|
|
37
|
+
// ── EncodingTier ─────────────────────────────────────────────────────────────
|
|
38
|
+
/**
|
|
39
|
+
* Wire encoding tier, stored in the lower 2 bits of the flags byte (NPS-1 §3.2).
|
|
40
|
+
* 0x00 = Tier-1 JSON — human-readable; development / compatibility.
|
|
41
|
+
* 0x01 = Tier-2 MsgPack — binary, ~60 % smaller; production default.
|
|
42
|
+
*/
|
|
43
|
+
export var EncodingTier;
|
|
44
|
+
(function (EncodingTier) {
|
|
45
|
+
EncodingTier[EncodingTier["JSON"] = 0] = "JSON";
|
|
46
|
+
EncodingTier[EncodingTier["MSGPACK"] = 1] = "MSGPACK";
|
|
47
|
+
})(EncodingTier || (EncodingTier = {}));
|
|
48
|
+
// ── FrameFlags ───────────────────────────────────────────────────────────────
|
|
49
|
+
/**
|
|
50
|
+
* Flags byte in the NPS frame header (NPS-1 §3.2).
|
|
51
|
+
* Bit layout (LSB = bit 0):
|
|
52
|
+
* Bits 0–1 (T0,T1) : Encoding tier
|
|
53
|
+
* Bit 2 (FINAL) : Last chunk of a StreamFrame; non-stream frames MUST set this
|
|
54
|
+
* Bit 3 (ENC) : Payload encrypted
|
|
55
|
+
* Bits 4–6 (RSV) : Reserved — sender MUST write 0
|
|
56
|
+
* Bit 7 (EXT) : Extended 8-byte header
|
|
57
|
+
*/
|
|
58
|
+
export const FrameFlags = {
|
|
59
|
+
NONE: 0x00,
|
|
60
|
+
TIER1_JSON: 0x00,
|
|
61
|
+
TIER2_MSGPACK: 0x01,
|
|
62
|
+
FINAL: 0x04,
|
|
63
|
+
ENCRYPTED: 0x08,
|
|
64
|
+
EXT: 0x80,
|
|
65
|
+
};
|
|
66
|
+
// ── Constants ─────────────────────────────────────────────────────────────────
|
|
67
|
+
export const DEFAULT_HEADER_SIZE = 4;
|
|
68
|
+
export const EXTENDED_HEADER_SIZE = 8;
|
|
69
|
+
export const DEFAULT_MAX_PAYLOAD = 0xffff; // 65 535 bytes
|
|
70
|
+
export const EXTENDED_MAX_PAYLOAD = 0xffffffff; // 4 GiB - 1
|
|
71
|
+
// ── FrameHeader ──────────────────────────────────────────────────────────────
|
|
72
|
+
/**
|
|
73
|
+
* NPS frame header, present at the start of every wire message (NPS-1 §3.1).
|
|
74
|
+
*
|
|
75
|
+
* Default (4 bytes, EXT=0):
|
|
76
|
+
* Byte 0 : FrameType
|
|
77
|
+
* Byte 1 : Flags
|
|
78
|
+
* Byte 2–3 : PayloadLength (big-endian uint16)
|
|
79
|
+
*
|
|
80
|
+
* Extended (8 bytes, EXT=1):
|
|
81
|
+
* Byte 0 : FrameType
|
|
82
|
+
* Byte 1 : Flags (bit 7 = 1)
|
|
83
|
+
* Byte 2–3 : Reserved (must be 0)
|
|
84
|
+
* Byte 4–7 : PayloadLength (big-endian uint32)
|
|
85
|
+
*/
|
|
86
|
+
export class FrameHeader {
|
|
87
|
+
frameType;
|
|
88
|
+
flags;
|
|
89
|
+
payloadLength;
|
|
90
|
+
constructor(frameType, flags, payloadLength) {
|
|
91
|
+
this.frameType = frameType;
|
|
92
|
+
this.flags = flags;
|
|
93
|
+
this.payloadLength = payloadLength;
|
|
94
|
+
}
|
|
95
|
+
get isExtended() {
|
|
96
|
+
return (this.flags & FrameFlags.EXT) !== 0;
|
|
97
|
+
}
|
|
98
|
+
get headerSize() {
|
|
99
|
+
return this.isExtended ? EXTENDED_HEADER_SIZE : DEFAULT_HEADER_SIZE;
|
|
100
|
+
}
|
|
101
|
+
get encodingTier() {
|
|
102
|
+
return (this.flags & 0x03);
|
|
103
|
+
}
|
|
104
|
+
get isFinal() {
|
|
105
|
+
return (this.flags & 0x04) !== 0;
|
|
106
|
+
}
|
|
107
|
+
get isEncrypted() {
|
|
108
|
+
return (this.flags & 0x08) !== 0;
|
|
109
|
+
}
|
|
110
|
+
// ── Parsing ───────────────────────────────────────────────────────────────
|
|
111
|
+
static parse(buf) {
|
|
112
|
+
if (buf.length < 2) {
|
|
113
|
+
throw new NpsFrameError(`Buffer too small to read frame type and flags: need >= 2 bytes, got ${buf.length}.`);
|
|
114
|
+
}
|
|
115
|
+
const flags = buf[1];
|
|
116
|
+
const ext = (flags & FrameFlags.EXT) !== 0;
|
|
117
|
+
if (ext) {
|
|
118
|
+
if (buf.length < EXTENDED_HEADER_SIZE) {
|
|
119
|
+
throw new NpsFrameError(`Buffer too small for extended frame header: need ${EXTENDED_HEADER_SIZE} bytes, got ${buf.length}.`);
|
|
120
|
+
}
|
|
121
|
+
const view = new DataView(buf.buffer, buf.byteOffset);
|
|
122
|
+
const payloadLength = view.getUint32(4, false); // big-endian
|
|
123
|
+
return new FrameHeader(buf[0], flags, payloadLength);
|
|
124
|
+
}
|
|
125
|
+
if (buf.length < DEFAULT_HEADER_SIZE) {
|
|
126
|
+
throw new NpsFrameError(`Buffer too small for frame header: need ${DEFAULT_HEADER_SIZE} bytes, got ${buf.length}.`);
|
|
127
|
+
}
|
|
128
|
+
const view = new DataView(buf.buffer, buf.byteOffset);
|
|
129
|
+
const payloadLength = view.getUint16(2, false); // big-endian
|
|
130
|
+
return new FrameHeader(buf[0], flags, payloadLength);
|
|
131
|
+
}
|
|
132
|
+
// ── Serialisation ─────────────────────────────────────────────────────────
|
|
133
|
+
toBytes() {
|
|
134
|
+
if (this.isExtended) {
|
|
135
|
+
const buf = new Uint8Array(EXTENDED_HEADER_SIZE);
|
|
136
|
+
const view = new DataView(buf.buffer);
|
|
137
|
+
view.setUint8(0, this.frameType);
|
|
138
|
+
view.setUint8(1, this.flags);
|
|
139
|
+
view.setUint16(2, 0, false); // reserved
|
|
140
|
+
view.setUint32(4, this.payloadLength, false);
|
|
141
|
+
return buf;
|
|
142
|
+
}
|
|
143
|
+
const buf = new Uint8Array(DEFAULT_HEADER_SIZE);
|
|
144
|
+
const view = new DataView(buf.buffer);
|
|
145
|
+
view.setUint8(0, this.frameType);
|
|
146
|
+
view.setUint8(1, this.flags);
|
|
147
|
+
view.setUint16(2, this.payloadLength, false);
|
|
148
|
+
return buf;
|
|
149
|
+
}
|
|
150
|
+
toString() {
|
|
151
|
+
return `FrameHeader(frameType=0x${this.frameType.toString(16).padStart(2, "0")}, flags=0x${this.flags.toString(16).padStart(2, "0")}, payloadLength=${this.payloadLength})`;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=frames.js.map
|