@labacacia/nps-sdk 1.0.0-alpha.1
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/CONTRIBUTING.md +33 -0
- package/LICENSE +170 -0
- package/NOTICE +7 -0
- package/README.md +153 -0
- package/dist/codec-CmHeovTV.d.cts +120 -0
- package/dist/codec-CmHeovTV.d.ts +120 -0
- package/dist/core/anchor-cache.d.ts +42 -0
- package/dist/core/anchor-cache.d.ts.map +1 -0
- package/dist/core/anchor-cache.js +104 -0
- package/dist/core/anchor-cache.js.map +1 -0
- package/dist/core/cache.d.ts +14 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +80 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/canonical-json.d.ts +12 -0
- package/dist/core/canonical-json.d.ts.map +1 -0
- package/dist/core/canonical-json.js +44 -0
- package/dist/core/canonical-json.js.map +1 -0
- package/dist/core/codec.d.ts +32 -0
- package/dist/core/codec.d.ts.map +1 -0
- package/dist/core/codec.js +119 -0
- package/dist/core/codec.js.map +1 -0
- package/dist/core/codecs/index.d.ts +4 -0
- package/dist/core/codecs/index.d.ts.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.d.ts +39 -0
- package/dist/core/codecs/ncp-codec.d.ts.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.d.ts +10 -0
- package/dist/core/codecs/tier1-json-codec.d.ts.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.d.ts +10 -0
- package/dist/core/codecs/tier2-msgpack-codec.d.ts.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.d.ts +31 -0
- package/dist/core/crypto-provider.d.ts.map +1 -0
- package/dist/core/crypto-provider.js +10 -0
- package/dist/core/crypto-provider.js.map +1 -0
- package/dist/core/exceptions.d.ts +27 -0
- package/dist/core/exceptions.d.ts.map +1 -0
- package/dist/core/exceptions.js +52 -0
- package/dist/core/exceptions.js.map +1 -0
- package/dist/core/frame-header.d.ts +87 -0
- package/dist/core/frame-header.d.ts.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.d.ts +35 -0
- package/dist/core/frame-registry.d.ts.map +1 -0
- package/dist/core/frame-registry.js +63 -0
- package/dist/core/frame-registry.js.map +1 -0
- package/dist/core/frames.d.ts +80 -0
- package/dist/core/frames.d.ts.map +1 -0
- package/dist/core/frames.js +153 -0
- package/dist/core/frames.js.map +1 -0
- package/dist/core/index.cjs +371 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +41 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +10 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/registry.d.ts +11 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/registry.js +17 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/core/status-codes.d.ts +28 -0
- package/dist/core/status-codes.d.ts.map +1 -0
- package/dist/core/status-codes.js +38 -0
- package/dist/core/status-codes.js.map +1 -0
- package/dist/frames-B3qLdl_g.d.cts +77 -0
- package/dist/frames-Ff7-ZPUl.d.ts +77 -0
- package/dist/index.cjs +1556 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +21 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/ncp/frames/anchor-frame.d.ts +29 -0
- package/dist/ncp/frames/anchor-frame.d.ts.map +1 -0
- 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.d.ts +29 -0
- package/dist/ncp/frames/caps-frame.d.ts.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.d.ts +32 -0
- package/dist/ncp/frames/diff-frame.d.ts.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.d.ts +16 -0
- package/dist/ncp/frames/error-frame.d.ts.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.d.ts +21 -0
- package/dist/ncp/frames/hello-frame.d.ts.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.d.ts +16 -0
- package/dist/ncp/frames/stream-frame.d.ts.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.d.ts +76 -0
- package/dist/ncp/frames.d.ts.map +1 -0
- package/dist/ncp/frames.js +147 -0
- package/dist/ncp/frames.js.map +1 -0
- package/dist/ncp/handshake.d.ts +30 -0
- package/dist/ncp/handshake.d.ts.map +1 -0
- package/dist/ncp/handshake.js +80 -0
- package/dist/ncp/handshake.js.map +1 -0
- package/dist/ncp/index.cjs +188 -0
- package/dist/ncp/index.cjs.map +1 -0
- package/dist/ncp/index.d.cts +6 -0
- package/dist/ncp/index.d.ts +11 -0
- package/dist/ncp/index.d.ts.map +1 -0
- package/dist/ncp/index.js +13 -0
- package/dist/ncp/index.js.map +1 -0
- package/dist/ncp/ncp-error-codes.d.ts +22 -0
- package/dist/ncp/ncp-error-codes.d.ts.map +1 -0
- package/dist/ncp/ncp-error-codes.js +32 -0
- package/dist/ncp/ncp-error-codes.js.map +1 -0
- package/dist/ncp/ncp-patch-format.d.ts +7 -0
- package/dist/ncp/ncp-patch-format.d.ts.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/registry.d.ts +3 -0
- package/dist/ncp/registry.d.ts.map +1 -0
- package/dist/ncp/registry.js +12 -0
- package/dist/ncp/registry.js.map +1 -0
- package/dist/ncp/stream-manager.d.ts +57 -0
- package/dist/ncp/stream-manager.d.ts.map +1 -0
- package/dist/ncp/stream-manager.js +163 -0
- package/dist/ncp/stream-manager.js.map +1 -0
- package/dist/ndp/frames.d.ts +56 -0
- package/dist/ndp/frames.d.ts.map +1 -0
- package/dist/ndp/frames.js +87 -0
- package/dist/ndp/frames.js.map +1 -0
- package/dist/ndp/index.cjs +252 -0
- package/dist/ndp/index.cjs.map +1 -0
- package/dist/ndp/index.d.cts +86 -0
- package/dist/ndp/index.d.ts +5 -0
- package/dist/ndp/index.d.ts.map +1 -0
- package/dist/ndp/index.js +7 -0
- package/dist/ndp/index.js.map +1 -0
- package/dist/ndp/ndp-registry.d.ts +11 -0
- package/dist/ndp/ndp-registry.d.ts.map +1 -0
- package/dist/ndp/ndp-registry.js +79 -0
- package/dist/ndp/ndp-registry.js.map +1 -0
- package/dist/ndp/registry.d.ts +3 -0
- package/dist/ndp/registry.d.ts.map +1 -0
- package/dist/ndp/registry.js +10 -0
- package/dist/ndp/registry.js.map +1 -0
- package/dist/ndp/validator.d.ts +18 -0
- package/dist/ndp/validator.d.ts.map +1 -0
- package/dist/ndp/validator.js +48 -0
- package/dist/ndp/validator.js.map +1 -0
- package/dist/nip/frames.d.ts +44 -0
- package/dist/nip/frames.d.ts.map +1 -0
- package/dist/nip/frames.js +81 -0
- package/dist/nip/frames.js.map +1 -0
- package/dist/nip/identity.d.ts +18 -0
- package/dist/nip/identity.d.ts.map +1 -0
- package/dist/nip/identity.js +94 -0
- package/dist/nip/identity.js.map +1 -0
- package/dist/nip/index.cjs +214 -0
- package/dist/nip/index.cjs.map +1 -0
- package/dist/nip/index.d.cts +65 -0
- package/dist/nip/index.d.ts +4 -0
- package/dist/nip/index.d.ts.map +1 -0
- package/dist/nip/index.js +6 -0
- package/dist/nip/index.js.map +1 -0
- package/dist/nip/registry.d.ts +3 -0
- package/dist/nip/registry.d.ts.map +1 -0
- package/dist/nip/registry.js +10 -0
- package/dist/nip/registry.js.map +1 -0
- package/dist/nop/client.d.ts +34 -0
- package/dist/nop/client.d.ts.map +1 -0
- package/dist/nop/client.js +90 -0
- package/dist/nop/client.js.map +1 -0
- package/dist/nop/frames.d.ts +65 -0
- package/dist/nop/frames.d.ts.map +1 -0
- package/dist/nop/frames.js +148 -0
- package/dist/nop/frames.js.map +1 -0
- package/dist/nop/index.cjs +762 -0
- package/dist/nop/index.cjs.map +1 -0
- package/dist/nop/index.d.cts +155 -0
- package/dist/nop/index.d.ts +5 -0
- package/dist/nop/index.d.ts.map +1 -0
- package/dist/nop/index.js +7 -0
- package/dist/nop/index.js.map +1 -0
- package/dist/nop/models.d.ts +58 -0
- package/dist/nop/models.d.ts.map +1 -0
- package/dist/nop/models.js +50 -0
- package/dist/nop/models.js.map +1 -0
- package/dist/nop/nop-types.d.ts +136 -0
- package/dist/nop/nop-types.d.ts.map +1 -0
- package/dist/nop/nop-types.js +44 -0
- package/dist/nop/nop-types.js.map +1 -0
- package/dist/nop/registry.d.ts +3 -0
- package/dist/nop/registry.d.ts.map +1 -0
- package/dist/nop/registry.js +11 -0
- package/dist/nop/registry.js.map +1 -0
- package/dist/nwp/client.d.ts +22 -0
- package/dist/nwp/client.d.ts.map +1 -0
- package/dist/nwp/client.js +101 -0
- package/dist/nwp/client.js.map +1 -0
- package/dist/nwp/frames.d.ts +46 -0
- package/dist/nwp/frames.d.ts.map +1 -0
- package/dist/nwp/frames.js +81 -0
- package/dist/nwp/frames.js.map +1 -0
- package/dist/nwp/index.cjs +658 -0
- package/dist/nwp/index.cjs.map +1 -0
- package/dist/nwp/index.d.cts +65 -0
- package/dist/nwp/index.d.ts +4 -0
- package/dist/nwp/index.d.ts.map +1 -0
- package/dist/nwp/index.js +6 -0
- package/dist/nwp/index.js.map +1 -0
- package/dist/nwp/registry.d.ts +3 -0
- package/dist/nwp/registry.d.ts.map +1 -0
- package/dist/nwp/registry.js +9 -0
- package/dist/nwp/registry.js.map +1 -0
- package/dist/setup.d.ts +10 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +29 -0
- package/dist/setup.js.map +1 -0
- package/nip-ca-server/Dockerfile +27 -0
- package/nip-ca-server/README.md +45 -0
- package/nip-ca-server/db/001_init.sql +25 -0
- package/nip-ca-server/docker-compose.yml +29 -0
- package/nip-ca-server/package.json +23 -0
- package/nip-ca-server/src/ca.ts +155 -0
- package/nip-ca-server/src/db.ts +104 -0
- package/nip-ca-server/src/index.ts +157 -0
- package/nip-ca-server/tsconfig.json +13 -0
- package/package.json +47 -0
- package/src/core/anchor-cache.ts +129 -0
- package/src/core/cache.ts +93 -0
- package/src/core/canonical-json.ts +50 -0
- package/src/core/codec.ts +158 -0
- package/src/core/codecs/index.ts +5 -0
- package/src/core/codecs/ncp-codec.ts +170 -0
- package/src/core/codecs/tier1-json-codec.ts +33 -0
- package/src/core/codecs/tier2-msgpack-codec.ts +30 -0
- package/src/core/crypto-provider.ts +47 -0
- package/src/core/exceptions.ts +57 -0
- package/src/core/frame-header.ts +282 -0
- package/src/core/frame-registry.ts +91 -0
- package/src/core/frames.ts +183 -0
- package/src/core/index.ts +10 -0
- package/src/core/registry.ts +28 -0
- package/src/core/status-codes.ts +46 -0
- package/src/index.ts +10 -0
- package/src/ncp/frames/anchor-frame.ts +87 -0
- package/src/ncp/frames/caps-frame.ts +59 -0
- package/src/ncp/frames/diff-frame.ts +69 -0
- package/src/ncp/frames/error-frame.ts +26 -0
- package/src/ncp/frames/hello-frame.ts +50 -0
- package/src/ncp/frames/stream-frame.ts +35 -0
- package/src/ncp/frames.ts +199 -0
- package/src/ncp/handshake.ts +95 -0
- package/src/ncp/index.ts +12 -0
- package/src/ncp/ncp-error-codes.ts +34 -0
- package/src/ncp/ncp-patch-format.ts +16 -0
- package/src/ncp/registry.ts +14 -0
- package/src/ncp/stream-manager.ts +212 -0
- package/src/ndp/frames.ts +124 -0
- package/src/ndp/index.ts +7 -0
- package/src/ndp/ndp-registry.ts +82 -0
- package/src/ndp/registry.ts +12 -0
- package/src/ndp/validator.ts +64 -0
- package/src/nip/frames.ts +106 -0
- package/src/nip/identity.ts +113 -0
- package/src/nip/index.ts +6 -0
- package/src/nip/registry.ts +12 -0
- package/src/nop/client.ts +103 -0
- package/src/nop/frames.ts +181 -0
- package/src/nop/index.ts +7 -0
- package/src/nop/models.ts +79 -0
- package/src/nop/nop-types.ts +208 -0
- package/src/nop/registry.ts +13 -0
- package/src/nwp/client.ts +114 -0
- package/src/nwp/frames.ts +116 -0
- package/src/nwp/index.ts +6 -0
- package/src/nwp/registry.ts +11 -0
- package/src/setup.ts +32 -0
- package/tests/core/anchor-cache.test.ts +242 -0
- package/tests/core/codec.test.ts +205 -0
- package/tests/core/frame-registry.test.ts +46 -0
- package/tests/core.test.ts +327 -0
- package/tests/ncp/diff-binary-bitset.test.ts +107 -0
- package/tests/ncp/e2e-enc-reject.test.ts +93 -0
- package/tests/ncp/err-error-frame.test.ts +152 -0
- package/tests/ncp/frames.test.ts +359 -0
- package/tests/ncp/framing.test.ts +233 -0
- package/tests/ncp/hello-frame.test.ts +122 -0
- package/tests/ncp/inline-anchor.test.ts +88 -0
- package/tests/ncp/security.test.ts +184 -0
- package/tests/ncp/stream-window.test.ts +167 -0
- package/tests/ncp/stream.test.ts +242 -0
- package/tests/ncp/version-negotiation.test.ts +123 -0
- package/tests/ndp.test.ts +271 -0
- package/tests/nip.test.ts +184 -0
- package/tests/nop.test.ts +344 -0
- package/tests/nwp.test.ts +237 -0
- package/tsconfig.json +20 -0
- package/tsup.config.ts +20 -0
- package/vitest.config.ts +10 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ed25519 = require('@noble/ed25519');
|
|
4
|
+
var sha512 = require('@noble/hashes/sha512');
|
|
5
|
+
|
|
6
|
+
function _interopNamespace(e) {
|
|
7
|
+
if (e && e.__esModule) return e;
|
|
8
|
+
var n = Object.create(null);
|
|
9
|
+
if (e) {
|
|
10
|
+
Object.keys(e).forEach(function (k) {
|
|
11
|
+
if (k !== 'default') {
|
|
12
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
13
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function () { return e[k]; }
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
n.default = e;
|
|
21
|
+
return Object.freeze(n);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var ed25519__namespace = /*#__PURE__*/_interopNamespace(ed25519);
|
|
25
|
+
|
|
26
|
+
// src/ndp/frames.ts
|
|
27
|
+
var AnnounceFrame = class _AnnounceFrame {
|
|
28
|
+
constructor(nid, addresses, capabilities, ttl, timestamp, signature, nodeType) {
|
|
29
|
+
this.nid = nid;
|
|
30
|
+
this.addresses = addresses;
|
|
31
|
+
this.capabilities = capabilities;
|
|
32
|
+
this.ttl = ttl;
|
|
33
|
+
this.timestamp = timestamp;
|
|
34
|
+
this.signature = signature;
|
|
35
|
+
this.nodeType = nodeType;
|
|
36
|
+
}
|
|
37
|
+
nid;
|
|
38
|
+
addresses;
|
|
39
|
+
capabilities;
|
|
40
|
+
ttl;
|
|
41
|
+
timestamp;
|
|
42
|
+
signature;
|
|
43
|
+
nodeType;
|
|
44
|
+
frameType = 48 /* ANNOUNCE */;
|
|
45
|
+
preferredTier = 1 /* MSGPACK */;
|
|
46
|
+
unsignedDict() {
|
|
47
|
+
return {
|
|
48
|
+
nid: this.nid,
|
|
49
|
+
addresses: this.addresses,
|
|
50
|
+
capabilities: this.capabilities,
|
|
51
|
+
ttl: this.ttl,
|
|
52
|
+
timestamp: this.timestamp,
|
|
53
|
+
node_type: this.nodeType ?? null
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
toDict() {
|
|
57
|
+
return { ...this.unsignedDict(), signature: this.signature };
|
|
58
|
+
}
|
|
59
|
+
static fromDict(data) {
|
|
60
|
+
return new _AnnounceFrame(
|
|
61
|
+
data["nid"],
|
|
62
|
+
data["addresses"],
|
|
63
|
+
data["capabilities"],
|
|
64
|
+
data["ttl"],
|
|
65
|
+
data["timestamp"],
|
|
66
|
+
data["signature"],
|
|
67
|
+
data["node_type"] ?? void 0
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var ResolveFrame = class _ResolveFrame {
|
|
72
|
+
constructor(target, requesterNid, resolved) {
|
|
73
|
+
this.target = target;
|
|
74
|
+
this.requesterNid = requesterNid;
|
|
75
|
+
this.resolved = resolved;
|
|
76
|
+
}
|
|
77
|
+
target;
|
|
78
|
+
requesterNid;
|
|
79
|
+
resolved;
|
|
80
|
+
frameType = 49 /* RESOLVE */;
|
|
81
|
+
preferredTier = 1 /* MSGPACK */;
|
|
82
|
+
toDict() {
|
|
83
|
+
return {
|
|
84
|
+
target: this.target,
|
|
85
|
+
requester_nid: this.requesterNid ?? null,
|
|
86
|
+
resolved: this.resolved ?? null
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
static fromDict(data) {
|
|
90
|
+
return new _ResolveFrame(
|
|
91
|
+
data["target"],
|
|
92
|
+
data["requester_nid"] ?? void 0,
|
|
93
|
+
data["resolved"] ?? void 0
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
var GraphFrame = class _GraphFrame {
|
|
98
|
+
constructor(seq, initialSync, nodes, patch) {
|
|
99
|
+
this.seq = seq;
|
|
100
|
+
this.initialSync = initialSync;
|
|
101
|
+
this.nodes = nodes;
|
|
102
|
+
this.patch = patch;
|
|
103
|
+
}
|
|
104
|
+
seq;
|
|
105
|
+
initialSync;
|
|
106
|
+
nodes;
|
|
107
|
+
patch;
|
|
108
|
+
frameType = 50 /* GRAPH */;
|
|
109
|
+
preferredTier = 1 /* MSGPACK */;
|
|
110
|
+
toDict() {
|
|
111
|
+
return {
|
|
112
|
+
seq: this.seq,
|
|
113
|
+
initial_sync: this.initialSync,
|
|
114
|
+
nodes: this.nodes ?? null,
|
|
115
|
+
patch: this.patch ?? null
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
static fromDict(data) {
|
|
119
|
+
return new _GraphFrame(
|
|
120
|
+
data["seq"],
|
|
121
|
+
data["initial_sync"],
|
|
122
|
+
data["nodes"] ?? void 0,
|
|
123
|
+
data["patch"] ?? void 0
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// src/ndp/registry.ts
|
|
129
|
+
function registerNdpFrames(registry) {
|
|
130
|
+
registry.register(48 /* ANNOUNCE */, AnnounceFrame);
|
|
131
|
+
registry.register(49 /* RESOLVE */, ResolveFrame);
|
|
132
|
+
registry.register(50 /* GRAPH */, GraphFrame);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// src/ndp/ndp-registry.ts
|
|
136
|
+
var InMemoryNdpRegistry = class _InMemoryNdpRegistry {
|
|
137
|
+
_store = /* @__PURE__ */ new Map();
|
|
138
|
+
// Replaceable for testing
|
|
139
|
+
clock = () => Date.now();
|
|
140
|
+
announce(frame) {
|
|
141
|
+
const expiresAt = this.clock() + frame.ttl * 1e3;
|
|
142
|
+
if (frame.ttl === 0) {
|
|
143
|
+
this._store.delete(frame.nid);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
this._store.set(frame.nid, { frame, expiresAt });
|
|
147
|
+
}
|
|
148
|
+
getByNid(nid) {
|
|
149
|
+
const entry = this._store.get(nid);
|
|
150
|
+
if (entry === void 0) return void 0;
|
|
151
|
+
if (this.clock() > entry.expiresAt) {
|
|
152
|
+
this._store.delete(nid);
|
|
153
|
+
return void 0;
|
|
154
|
+
}
|
|
155
|
+
return entry.frame;
|
|
156
|
+
}
|
|
157
|
+
resolve(target) {
|
|
158
|
+
for (const [nid, entry] of this._store) {
|
|
159
|
+
if (this.clock() > entry.expiresAt) {
|
|
160
|
+
this._store.delete(nid);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (!_InMemoryNdpRegistry.nwpTargetMatchesNid(nid, target)) continue;
|
|
164
|
+
const addr = entry.frame.addresses[0];
|
|
165
|
+
if (addr === void 0) continue;
|
|
166
|
+
return { host: addr.host, port: addr.port, ttl: entry.frame.ttl };
|
|
167
|
+
}
|
|
168
|
+
return void 0;
|
|
169
|
+
}
|
|
170
|
+
getAll() {
|
|
171
|
+
const now = this.clock();
|
|
172
|
+
const result = [];
|
|
173
|
+
for (const [nid, entry] of this._store) {
|
|
174
|
+
if (now > entry.expiresAt) {
|
|
175
|
+
this._store.delete(nid);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
result.push(entry.frame);
|
|
179
|
+
}
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
static nwpTargetMatchesNid(nid, target) {
|
|
183
|
+
const nidParts = nid.split(":");
|
|
184
|
+
if (nidParts.length < 5 || nidParts[0] !== "urn" || nidParts[1] !== "nps" || nidParts[2] !== "node") {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
if (!target.startsWith("nwp://")) return false;
|
|
188
|
+
const nidAuthority = nidParts[3];
|
|
189
|
+
const nidPath = nidParts[4];
|
|
190
|
+
const rest = target.slice("nwp://".length);
|
|
191
|
+
const slashIdx = rest.indexOf("/");
|
|
192
|
+
if (slashIdx === -1) return false;
|
|
193
|
+
const urlAuthority = rest.slice(0, slashIdx);
|
|
194
|
+
const urlPath = rest.slice(slashIdx + 1);
|
|
195
|
+
if (urlAuthority !== nidAuthority) return false;
|
|
196
|
+
if (urlPath === nidPath) return true;
|
|
197
|
+
if (urlPath.startsWith(nidPath + "/")) return true;
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
ed25519__namespace.etc.sha512Sync = (...m) => sha512.sha512(ed25519__namespace.etc.concatBytes(...m));
|
|
202
|
+
var NdpAnnounceResult = {
|
|
203
|
+
ok: () => ({ isValid: true }),
|
|
204
|
+
fail: (errorCode, message) => ({ isValid: false, errorCode, message })
|
|
205
|
+
};
|
|
206
|
+
var NdpAnnounceValidator = class {
|
|
207
|
+
_keys = /* @__PURE__ */ new Map();
|
|
208
|
+
// nid → "ed25519:<hex>"
|
|
209
|
+
registerPublicKey(nid, encodedPubKey) {
|
|
210
|
+
this._keys.set(nid, encodedPubKey);
|
|
211
|
+
}
|
|
212
|
+
removePublicKey(nid) {
|
|
213
|
+
this._keys.delete(nid);
|
|
214
|
+
}
|
|
215
|
+
get knownPublicKeys() {
|
|
216
|
+
return this._keys;
|
|
217
|
+
}
|
|
218
|
+
validate(frame) {
|
|
219
|
+
const encoded = this._keys.get(frame.nid);
|
|
220
|
+
if (encoded === void 0) {
|
|
221
|
+
return NdpAnnounceResult.fail("NDP-ANNOUNCE-NID-MISMATCH", `No public key registered for NID: ${frame.nid}`);
|
|
222
|
+
}
|
|
223
|
+
try {
|
|
224
|
+
const prefix = "ed25519:";
|
|
225
|
+
const pubHex = encoded.startsWith(prefix) ? encoded.slice(prefix.length) : encoded;
|
|
226
|
+
const pubKey = Buffer.from(pubHex, "hex");
|
|
227
|
+
const sig = frame.signature;
|
|
228
|
+
if (!sig.startsWith(prefix)) {
|
|
229
|
+
return NdpAnnounceResult.fail("NDP-ANNOUNCE-SIG-INVALID", "Signature must start with 'ed25519:'");
|
|
230
|
+
}
|
|
231
|
+
const sigBytes = Buffer.from(sig.slice(prefix.length), "base64");
|
|
232
|
+
const unsigned = frame.unsignedDict();
|
|
233
|
+
const canonical = JSON.stringify(unsigned, Object.keys(unsigned).sort());
|
|
234
|
+
const message = new TextEncoder().encode(canonical);
|
|
235
|
+
const valid = ed25519__namespace.verify(sigBytes, message, pubKey);
|
|
236
|
+
if (!valid) return NdpAnnounceResult.fail("NDP-ANNOUNCE-SIG-INVALID", "Ed25519 signature verification failed.");
|
|
237
|
+
return NdpAnnounceResult.ok();
|
|
238
|
+
} catch {
|
|
239
|
+
return NdpAnnounceResult.fail("NDP-ANNOUNCE-SIG-INVALID", "Ed25519 signature verification failed.");
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
exports.AnnounceFrame = AnnounceFrame;
|
|
245
|
+
exports.GraphFrame = GraphFrame;
|
|
246
|
+
exports.InMemoryNdpRegistry = InMemoryNdpRegistry;
|
|
247
|
+
exports.NdpAnnounceResult = NdpAnnounceResult;
|
|
248
|
+
exports.NdpAnnounceValidator = NdpAnnounceValidator;
|
|
249
|
+
exports.ResolveFrame = ResolveFrame;
|
|
250
|
+
exports.registerNdpFrames = registerNdpFrames;
|
|
251
|
+
//# sourceMappingURL=index.cjs.map
|
|
252
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/ndp/frames.ts","../../src/ndp/registry.ts","../../src/ndp/ndp-registry.ts","../../src/ndp/validator.ts"],"names":["ed25519","sha512"],"mappings":"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","file":"index.cjs","sourcesContent":["// Copyright 2026 INNO LOTUS PTY LTD\n// SPDX-License-Identifier: Apache-2.0\n\nimport { EncodingTier, FrameType } from \"../core/frames.js\";\nimport type { NpsFrame } from \"../core/codec.js\";\n\nexport interface NdpAddress {\n host: string;\n port: number;\n protocol: string;\n}\n\nexport interface NdpGraphNode {\n nid: string;\n addresses: readonly NdpAddress[];\n capabilities: readonly string[];\n nodeType?: string;\n}\n\nexport interface NdpResolveResult {\n host: string;\n port: number;\n ttl: number;\n certFingerprint?: string;\n}\n\nexport class AnnounceFrame implements NpsFrame {\n readonly frameType = FrameType.ANNOUNCE;\n readonly preferredTier = EncodingTier.MSGPACK;\n\n constructor(\n public readonly nid: string,\n public readonly addresses: readonly NdpAddress[],\n public readonly capabilities: readonly string[],\n public readonly ttl: number,\n public readonly timestamp: string,\n public readonly signature: string,\n public readonly nodeType?: string,\n ) {}\n\n unsignedDict(): Record<string, unknown> {\n return {\n nid: this.nid,\n addresses: this.addresses,\n capabilities: this.capabilities,\n ttl: this.ttl,\n timestamp: this.timestamp,\n node_type: this.nodeType ?? null,\n };\n }\n\n toDict(): Record<string, unknown> {\n return { ...this.unsignedDict(), signature: this.signature };\n }\n\n static fromDict(data: Record<string, unknown>): AnnounceFrame {\n return new AnnounceFrame(\n data[\"nid\"] as string,\n data[\"addresses\"] as NdpAddress[],\n data[\"capabilities\"] as string[],\n data[\"ttl\"] as number,\n data[\"timestamp\"] as string,\n data[\"signature\"] as string,\n (data[\"node_type\"] as string | null) ?? undefined,\n );\n }\n}\n\nexport class ResolveFrame implements NpsFrame {\n readonly frameType = FrameType.RESOLVE;\n readonly preferredTier = EncodingTier.MSGPACK;\n\n constructor(\n public readonly target: string,\n public readonly requesterNid?: string,\n public readonly resolved?: NdpResolveResult,\n ) {}\n\n toDict(): Record<string, unknown> {\n return {\n target: this.target,\n requester_nid: this.requesterNid ?? null,\n resolved: this.resolved ?? null,\n };\n }\n\n static fromDict(data: Record<string, unknown>): ResolveFrame {\n return new ResolveFrame(\n data[\"target\"] as string,\n (data[\"requester_nid\"] as string | null) ?? undefined,\n (data[\"resolved\"] as NdpResolveResult | null) ?? undefined,\n );\n }\n}\n\nexport class GraphFrame implements NpsFrame {\n readonly frameType = FrameType.GRAPH;\n readonly preferredTier = EncodingTier.MSGPACK;\n\n constructor(\n public readonly seq: number,\n public readonly initialSync: boolean,\n public readonly nodes?: readonly NdpGraphNode[],\n public readonly patch?: readonly Record<string, unknown>[],\n ) {}\n\n toDict(): Record<string, unknown> {\n return {\n seq: this.seq,\n initial_sync: this.initialSync,\n nodes: this.nodes ?? null,\n patch: this.patch ?? null,\n };\n }\n\n static fromDict(data: Record<string, unknown>): GraphFrame {\n return new GraphFrame(\n data[\"seq\"] as number,\n data[\"initial_sync\"] as boolean,\n (data[\"nodes\"] as NdpGraphNode[] | null) ?? undefined,\n (data[\"patch\"] as Record<string, unknown>[] | null) ?? undefined,\n );\n }\n}\n","// Copyright 2026 INNO LOTUS PTY LTD\n// SPDX-License-Identifier: Apache-2.0\n\nimport { FrameRegistry } from \"../core/registry.js\";\nimport { FrameType } from \"../core/frames.js\";\nimport { AnnounceFrame, GraphFrame, ResolveFrame } from \"./frames.js\";\n\nexport function registerNdpFrames(registry: FrameRegistry): void {\n registry.register(FrameType.ANNOUNCE, AnnounceFrame);\n registry.register(FrameType.RESOLVE, ResolveFrame);\n registry.register(FrameType.GRAPH, GraphFrame);\n}\n","// Copyright 2026 INNO LOTUS PTY LTD\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { AnnounceFrame, NdpResolveResult } from \"./frames.js\";\n\ninterface RegistryEntry {\n frame: AnnounceFrame;\n expiresAt: number;\n}\n\nexport class InMemoryNdpRegistry {\n private readonly _store = new Map<string, RegistryEntry>();\n\n // Replaceable for testing\n clock: () => number = () => Date.now();\n\n announce(frame: AnnounceFrame): void {\n const expiresAt = this.clock() + frame.ttl * 1000;\n if (frame.ttl === 0) {\n this._store.delete(frame.nid);\n return;\n }\n this._store.set(frame.nid, { frame, expiresAt });\n }\n\n getByNid(nid: string): AnnounceFrame | undefined {\n const entry = this._store.get(nid);\n if (entry === undefined) return undefined;\n if (this.clock() > entry.expiresAt) {\n this._store.delete(nid);\n return undefined;\n }\n return entry.frame;\n }\n\n resolve(target: string): NdpResolveResult | undefined {\n for (const [nid, entry] of this._store) {\n if (this.clock() > entry.expiresAt) { this._store.delete(nid); continue; }\n if (!InMemoryNdpRegistry.nwpTargetMatchesNid(nid, target)) continue;\n const addr = entry.frame.addresses[0];\n if (addr === undefined) continue;\n return { host: addr.host, port: addr.port, ttl: entry.frame.ttl };\n }\n return undefined;\n }\n\n getAll(): AnnounceFrame[] {\n const now = this.clock();\n const result: AnnounceFrame[] = [];\n for (const [nid, entry] of this._store) {\n if (now > entry.expiresAt) { this._store.delete(nid); continue; }\n result.push(entry.frame);\n }\n return result;\n }\n\n static nwpTargetMatchesNid(nid: string, target: string): boolean {\n // NID: urn:nps:node:{authority}:{path-segment}\n // target: nwp://{authority}/{path}\n const nidParts = nid.split(\":\");\n if (nidParts.length < 5 || nidParts[0] !== \"urn\" || nidParts[1] !== \"nps\" || nidParts[2] !== \"node\") {\n return false;\n }\n if (!target.startsWith(\"nwp://\")) return false;\n\n const nidAuthority = nidParts[3]!;\n const nidPath = nidParts[4]!;\n const rest = target.slice(\"nwp://\".length);\n const slashIdx = rest.indexOf(\"/\");\n if (slashIdx === -1) return false;\n\n const urlAuthority = rest.slice(0, slashIdx);\n const urlPath = rest.slice(slashIdx + 1); // without leading slash\n\n if (urlAuthority !== nidAuthority) return false;\n\n // nidPath must be a prefix of urlPath at a segment boundary\n if (urlPath === nidPath) return true;\n if (urlPath.startsWith(nidPath + \"/\")) return true;\n return false;\n }\n}\n","// Copyright 2026 INNO LOTUS PTY LTD\n// SPDX-License-Identifier: Apache-2.0\n\nimport * as ed25519 from \"@noble/ed25519\";\nimport { sha512 } from \"@noble/hashes/sha512\";\nimport type { AnnounceFrame } from \"./frames.js\";\n\ned25519.etc.sha512Sync = (...m) => sha512(ed25519.etc.concatBytes(...m));\n\nexport interface NdpAnnounceResult {\n isValid: boolean;\n errorCode?: string;\n message?: string;\n}\n\nexport const NdpAnnounceResult = {\n ok: (): NdpAnnounceResult => ({ isValid: true }),\n fail: (errorCode: string, message: string): NdpAnnounceResult => ({ isValid: false, errorCode, message }),\n};\n\nexport class NdpAnnounceValidator {\n private readonly _keys = new Map<string, string>(); // nid → \"ed25519:<hex>\"\n\n registerPublicKey(nid: string, encodedPubKey: string): void {\n this._keys.set(nid, encodedPubKey);\n }\n\n removePublicKey(nid: string): void {\n this._keys.delete(nid);\n }\n\n get knownPublicKeys(): ReadonlyMap<string, string> {\n return this._keys;\n }\n\n validate(frame: AnnounceFrame): NdpAnnounceResult {\n const encoded = this._keys.get(frame.nid);\n if (encoded === undefined) {\n return NdpAnnounceResult.fail(\"NDP-ANNOUNCE-NID-MISMATCH\", `No public key registered for NID: ${frame.nid}`);\n }\n\n try {\n const prefix = \"ed25519:\";\n const pubHex = encoded.startsWith(prefix) ? encoded.slice(prefix.length) : encoded;\n const pubKey = Buffer.from(pubHex, \"hex\");\n\n const sig = frame.signature;\n if (!sig.startsWith(prefix)) {\n return NdpAnnounceResult.fail(\"NDP-ANNOUNCE-SIG-INVALID\", \"Signature must start with 'ed25519:'\");\n }\n const sigBytes = Buffer.from(sig.slice(prefix.length), \"base64\");\n\n const unsigned = frame.unsignedDict();\n const canonical = JSON.stringify(unsigned, Object.keys(unsigned).sort());\n const message = new TextEncoder().encode(canonical);\n\n const valid = ed25519.verify(sigBytes, message, pubKey);\n if (!valid) return NdpAnnounceResult.fail(\"NDP-ANNOUNCE-SIG-INVALID\", \"Ed25519 signature verification failed.\");\n return NdpAnnounceResult.ok();\n } catch {\n return NdpAnnounceResult.fail(\"NDP-ANNOUNCE-SIG-INVALID\", \"Ed25519 signature verification failed.\");\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { N as NpsFrame, g as FrameType, c as EncodingTier, F as FrameRegistry } from '../codec-CmHeovTV.cjs';
|
|
2
|
+
|
|
3
|
+
interface NdpAddress {
|
|
4
|
+
host: string;
|
|
5
|
+
port: number;
|
|
6
|
+
protocol: string;
|
|
7
|
+
}
|
|
8
|
+
interface NdpGraphNode {
|
|
9
|
+
nid: string;
|
|
10
|
+
addresses: readonly NdpAddress[];
|
|
11
|
+
capabilities: readonly string[];
|
|
12
|
+
nodeType?: string;
|
|
13
|
+
}
|
|
14
|
+
interface NdpResolveResult {
|
|
15
|
+
host: string;
|
|
16
|
+
port: number;
|
|
17
|
+
ttl: number;
|
|
18
|
+
certFingerprint?: string;
|
|
19
|
+
}
|
|
20
|
+
declare class AnnounceFrame implements NpsFrame {
|
|
21
|
+
readonly nid: string;
|
|
22
|
+
readonly addresses: readonly NdpAddress[];
|
|
23
|
+
readonly capabilities: readonly string[];
|
|
24
|
+
readonly ttl: number;
|
|
25
|
+
readonly timestamp: string;
|
|
26
|
+
readonly signature: string;
|
|
27
|
+
readonly nodeType?: string | undefined;
|
|
28
|
+
readonly frameType = FrameType.ANNOUNCE;
|
|
29
|
+
readonly preferredTier = EncodingTier.MSGPACK;
|
|
30
|
+
constructor(nid: string, addresses: readonly NdpAddress[], capabilities: readonly string[], ttl: number, timestamp: string, signature: string, nodeType?: string | undefined);
|
|
31
|
+
unsignedDict(): Record<string, unknown>;
|
|
32
|
+
toDict(): Record<string, unknown>;
|
|
33
|
+
static fromDict(data: Record<string, unknown>): AnnounceFrame;
|
|
34
|
+
}
|
|
35
|
+
declare class ResolveFrame implements NpsFrame {
|
|
36
|
+
readonly target: string;
|
|
37
|
+
readonly requesterNid?: string | undefined;
|
|
38
|
+
readonly resolved?: NdpResolveResult | undefined;
|
|
39
|
+
readonly frameType = FrameType.RESOLVE;
|
|
40
|
+
readonly preferredTier = EncodingTier.MSGPACK;
|
|
41
|
+
constructor(target: string, requesterNid?: string | undefined, resolved?: NdpResolveResult | undefined);
|
|
42
|
+
toDict(): Record<string, unknown>;
|
|
43
|
+
static fromDict(data: Record<string, unknown>): ResolveFrame;
|
|
44
|
+
}
|
|
45
|
+
declare class GraphFrame implements NpsFrame {
|
|
46
|
+
readonly seq: number;
|
|
47
|
+
readonly initialSync: boolean;
|
|
48
|
+
readonly nodes?: readonly NdpGraphNode[] | undefined;
|
|
49
|
+
readonly patch?: readonly Record<string, unknown>[] | undefined;
|
|
50
|
+
readonly frameType = FrameType.GRAPH;
|
|
51
|
+
readonly preferredTier = EncodingTier.MSGPACK;
|
|
52
|
+
constructor(seq: number, initialSync: boolean, nodes?: readonly NdpGraphNode[] | undefined, patch?: readonly Record<string, unknown>[] | undefined);
|
|
53
|
+
toDict(): Record<string, unknown>;
|
|
54
|
+
static fromDict(data: Record<string, unknown>): GraphFrame;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
declare function registerNdpFrames(registry: FrameRegistry): void;
|
|
58
|
+
|
|
59
|
+
declare class InMemoryNdpRegistry {
|
|
60
|
+
private readonly _store;
|
|
61
|
+
clock: () => number;
|
|
62
|
+
announce(frame: AnnounceFrame): void;
|
|
63
|
+
getByNid(nid: string): AnnounceFrame | undefined;
|
|
64
|
+
resolve(target: string): NdpResolveResult | undefined;
|
|
65
|
+
getAll(): AnnounceFrame[];
|
|
66
|
+
static nwpTargetMatchesNid(nid: string, target: string): boolean;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface NdpAnnounceResult {
|
|
70
|
+
isValid: boolean;
|
|
71
|
+
errorCode?: string;
|
|
72
|
+
message?: string;
|
|
73
|
+
}
|
|
74
|
+
declare const NdpAnnounceResult: {
|
|
75
|
+
ok: () => NdpAnnounceResult;
|
|
76
|
+
fail: (errorCode: string, message: string) => NdpAnnounceResult;
|
|
77
|
+
};
|
|
78
|
+
declare class NdpAnnounceValidator {
|
|
79
|
+
private readonly _keys;
|
|
80
|
+
registerPublicKey(nid: string, encodedPubKey: string): void;
|
|
81
|
+
removePublicKey(nid: string): void;
|
|
82
|
+
get knownPublicKeys(): ReadonlyMap<string, string>;
|
|
83
|
+
validate(frame: AnnounceFrame): NdpAnnounceResult;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export { AnnounceFrame, GraphFrame, InMemoryNdpRegistry, type NdpAddress, NdpAnnounceResult, NdpAnnounceValidator, type NdpGraphNode, type NdpResolveResult, ResolveFrame, registerNdpFrames };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ndp/index.ts"],"names":[],"mappings":"AAGA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ndp/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;AAEtC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AnnounceFrame, NdpResolveResult } from "./frames.js";
|
|
2
|
+
export declare class InMemoryNdpRegistry {
|
|
3
|
+
private readonly _store;
|
|
4
|
+
clock: () => number;
|
|
5
|
+
announce(frame: AnnounceFrame): void;
|
|
6
|
+
getByNid(nid: string): AnnounceFrame | undefined;
|
|
7
|
+
resolve(target: string): NdpResolveResult | undefined;
|
|
8
|
+
getAll(): AnnounceFrame[];
|
|
9
|
+
static nwpTargetMatchesNid(nid: string, target: string): boolean;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=ndp-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ndp-registry.d.ts","sourceRoot":"","sources":["../../src/ndp/ndp-registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAOnE,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoC;IAG3D,KAAK,EAAE,MAAM,MAAM,CAAoB;IAEvC,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IASpC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAUhD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAWrD,MAAM,IAAI,aAAa,EAAE;IAUzB,MAAM,CAAC,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;CAyBjE"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Copyright 2026 INNO LOTUS PTY LTD
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
export class InMemoryNdpRegistry {
|
|
4
|
+
_store = new Map();
|
|
5
|
+
// Replaceable for testing
|
|
6
|
+
clock = () => Date.now();
|
|
7
|
+
announce(frame) {
|
|
8
|
+
const expiresAt = this.clock() + frame.ttl * 1000;
|
|
9
|
+
if (frame.ttl === 0) {
|
|
10
|
+
this._store.delete(frame.nid);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
this._store.set(frame.nid, { frame, expiresAt });
|
|
14
|
+
}
|
|
15
|
+
getByNid(nid) {
|
|
16
|
+
const entry = this._store.get(nid);
|
|
17
|
+
if (entry === undefined)
|
|
18
|
+
return undefined;
|
|
19
|
+
if (this.clock() > entry.expiresAt) {
|
|
20
|
+
this._store.delete(nid);
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
return entry.frame;
|
|
24
|
+
}
|
|
25
|
+
resolve(target) {
|
|
26
|
+
for (const [nid, entry] of this._store) {
|
|
27
|
+
if (this.clock() > entry.expiresAt) {
|
|
28
|
+
this._store.delete(nid);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (!InMemoryNdpRegistry.nwpTargetMatchesNid(nid, target))
|
|
32
|
+
continue;
|
|
33
|
+
const addr = entry.frame.addresses[0];
|
|
34
|
+
if (addr === undefined)
|
|
35
|
+
continue;
|
|
36
|
+
return { host: addr.host, port: addr.port, ttl: entry.frame.ttl };
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
getAll() {
|
|
41
|
+
const now = this.clock();
|
|
42
|
+
const result = [];
|
|
43
|
+
for (const [nid, entry] of this._store) {
|
|
44
|
+
if (now > entry.expiresAt) {
|
|
45
|
+
this._store.delete(nid);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
result.push(entry.frame);
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
static nwpTargetMatchesNid(nid, target) {
|
|
53
|
+
// NID: urn:nps:node:{authority}:{path-segment}
|
|
54
|
+
// target: nwp://{authority}/{path}
|
|
55
|
+
const nidParts = nid.split(":");
|
|
56
|
+
if (nidParts.length < 5 || nidParts[0] !== "urn" || nidParts[1] !== "nps" || nidParts[2] !== "node") {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
if (!target.startsWith("nwp://"))
|
|
60
|
+
return false;
|
|
61
|
+
const nidAuthority = nidParts[3];
|
|
62
|
+
const nidPath = nidParts[4];
|
|
63
|
+
const rest = target.slice("nwp://".length);
|
|
64
|
+
const slashIdx = rest.indexOf("/");
|
|
65
|
+
if (slashIdx === -1)
|
|
66
|
+
return false;
|
|
67
|
+
const urlAuthority = rest.slice(0, slashIdx);
|
|
68
|
+
const urlPath = rest.slice(slashIdx + 1); // without leading slash
|
|
69
|
+
if (urlAuthority !== nidAuthority)
|
|
70
|
+
return false;
|
|
71
|
+
// nidPath must be a prefix of urlPath at a segment boundary
|
|
72
|
+
if (urlPath === nidPath)
|
|
73
|
+
return true;
|
|
74
|
+
if (urlPath.startsWith(nidPath + "/"))
|
|
75
|
+
return true;
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=ndp-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ndp-registry.js","sourceRoot":"","sources":["../../src/ndp/ndp-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/ndp/registry.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIpD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAI/D"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Copyright 2026 INNO LOTUS PTY LTD
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { FrameType } from "../core/frames.js";
|
|
4
|
+
import { AnnounceFrame, GraphFrame, ResolveFrame } from "./frames.js";
|
|
5
|
+
export function registerNdpFrames(registry) {
|
|
6
|
+
registry.register(FrameType.ANNOUNCE, AnnounceFrame);
|
|
7
|
+
registry.register(FrameType.RESOLVE, ResolveFrame);
|
|
8
|
+
registry.register(FrameType.GRAPH, GraphFrame);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/ndp/registry.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;AAGtC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEtE,MAAM,UAAU,iBAAiB,CAAC,QAAuB;IACvD,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACrD,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAG,YAAY,CAAC,CAAC;IACpD,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,EAAK,UAAU,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AnnounceFrame } from "./frames.js";
|
|
2
|
+
export interface NdpAnnounceResult {
|
|
3
|
+
isValid: boolean;
|
|
4
|
+
errorCode?: string;
|
|
5
|
+
message?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const NdpAnnounceResult: {
|
|
8
|
+
ok: () => NdpAnnounceResult;
|
|
9
|
+
fail: (errorCode: string, message: string) => NdpAnnounceResult;
|
|
10
|
+
};
|
|
11
|
+
export declare class NdpAnnounceValidator {
|
|
12
|
+
private readonly _keys;
|
|
13
|
+
registerPublicKey(nid: string, encodedPubKey: string): void;
|
|
14
|
+
removePublicKey(nid: string): void;
|
|
15
|
+
get knownPublicKeys(): ReadonlyMap<string, string>;
|
|
16
|
+
validate(frame: AnnounceFrame): NdpAnnounceResult;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/ndp/validator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAK,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAI,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,iBAAiB;cACpB,iBAAiB;sBACP,MAAM,WAAW,MAAM,KAAG,iBAAiB;CAC9D,CAAC;AAEF,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6B;IAEnD,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAI3D,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIlC,IAAI,eAAe,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAEjD;IAED,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,iBAAiB;CA4BlD"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Copyright 2026 INNO LOTUS PTY LTD
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import * as ed25519 from "@noble/ed25519";
|
|
4
|
+
import { sha512 } from "@noble/hashes/sha512";
|
|
5
|
+
ed25519.etc.sha512Sync = (...m) => sha512(ed25519.etc.concatBytes(...m));
|
|
6
|
+
export const NdpAnnounceResult = {
|
|
7
|
+
ok: () => ({ isValid: true }),
|
|
8
|
+
fail: (errorCode, message) => ({ isValid: false, errorCode, message }),
|
|
9
|
+
};
|
|
10
|
+
export class NdpAnnounceValidator {
|
|
11
|
+
_keys = new Map(); // nid → "ed25519:<hex>"
|
|
12
|
+
registerPublicKey(nid, encodedPubKey) {
|
|
13
|
+
this._keys.set(nid, encodedPubKey);
|
|
14
|
+
}
|
|
15
|
+
removePublicKey(nid) {
|
|
16
|
+
this._keys.delete(nid);
|
|
17
|
+
}
|
|
18
|
+
get knownPublicKeys() {
|
|
19
|
+
return this._keys;
|
|
20
|
+
}
|
|
21
|
+
validate(frame) {
|
|
22
|
+
const encoded = this._keys.get(frame.nid);
|
|
23
|
+
if (encoded === undefined) {
|
|
24
|
+
return NdpAnnounceResult.fail("NDP-ANNOUNCE-NID-MISMATCH", `No public key registered for NID: ${frame.nid}`);
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const prefix = "ed25519:";
|
|
28
|
+
const pubHex = encoded.startsWith(prefix) ? encoded.slice(prefix.length) : encoded;
|
|
29
|
+
const pubKey = Buffer.from(pubHex, "hex");
|
|
30
|
+
const sig = frame.signature;
|
|
31
|
+
if (!sig.startsWith(prefix)) {
|
|
32
|
+
return NdpAnnounceResult.fail("NDP-ANNOUNCE-SIG-INVALID", "Signature must start with 'ed25519:'");
|
|
33
|
+
}
|
|
34
|
+
const sigBytes = Buffer.from(sig.slice(prefix.length), "base64");
|
|
35
|
+
const unsigned = frame.unsignedDict();
|
|
36
|
+
const canonical = JSON.stringify(unsigned, Object.keys(unsigned).sort());
|
|
37
|
+
const message = new TextEncoder().encode(canonical);
|
|
38
|
+
const valid = ed25519.verify(sigBytes, message, pubKey);
|
|
39
|
+
if (!valid)
|
|
40
|
+
return NdpAnnounceResult.fail("NDP-ANNOUNCE-SIG-INVALID", "Ed25519 signature verification failed.");
|
|
41
|
+
return NdpAnnounceResult.ok();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return NdpAnnounceResult.fail("NDP-ANNOUNCE-SIG-INVALID", "Ed25519 signature verification failed.");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/ndp/validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { EncodingTier, FrameType } from "../core/frames.js";
|
|
2
|
+
import type { NpsFrame } from "../core/codec.js";
|
|
3
|
+
export interface IdentMetadata {
|
|
4
|
+
issuer: string;
|
|
5
|
+
issuedAt: string;
|
|
6
|
+
expiresAt?: string;
|
|
7
|
+
capabilities?: readonly string[];
|
|
8
|
+
scopes?: readonly string[];
|
|
9
|
+
}
|
|
10
|
+
export declare class IdentFrame implements NpsFrame {
|
|
11
|
+
readonly nid: string;
|
|
12
|
+
readonly pubKey: string;
|
|
13
|
+
readonly metadata: IdentMetadata;
|
|
14
|
+
readonly signature: string;
|
|
15
|
+
readonly frameType = FrameType.IDENT;
|
|
16
|
+
readonly preferredTier = EncodingTier.MSGPACK;
|
|
17
|
+
constructor(nid: string, pubKey: string, metadata: IdentMetadata, signature: string);
|
|
18
|
+
unsignedDict(): Record<string, unknown>;
|
|
19
|
+
toDict(): Record<string, unknown>;
|
|
20
|
+
static fromDict(data: Record<string, unknown>): IdentFrame;
|
|
21
|
+
}
|
|
22
|
+
export declare class TrustFrame implements NpsFrame {
|
|
23
|
+
readonly issuerNid: string;
|
|
24
|
+
readonly subjectNid: string;
|
|
25
|
+
readonly scopes: readonly string[];
|
|
26
|
+
readonly expiresAt: string;
|
|
27
|
+
readonly signature: string;
|
|
28
|
+
readonly frameType = FrameType.TRUST;
|
|
29
|
+
readonly preferredTier = EncodingTier.MSGPACK;
|
|
30
|
+
constructor(issuerNid: string, subjectNid: string, scopes: readonly string[], expiresAt: string, signature: string);
|
|
31
|
+
toDict(): Record<string, unknown>;
|
|
32
|
+
static fromDict(data: Record<string, unknown>): TrustFrame;
|
|
33
|
+
}
|
|
34
|
+
export declare class RevokeFrame implements NpsFrame {
|
|
35
|
+
readonly nid: string;
|
|
36
|
+
readonly reason?: string | undefined;
|
|
37
|
+
readonly revokedAt?: string | undefined;
|
|
38
|
+
readonly frameType = FrameType.REVOKE;
|
|
39
|
+
readonly preferredTier = EncodingTier.MSGPACK;
|
|
40
|
+
constructor(nid: string, reason?: string | undefined, revokedAt?: string | undefined);
|
|
41
|
+
toDict(): Record<string, unknown>;
|
|
42
|
+
static fromDict(data: Record<string, unknown>): RevokeFrame;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=frames.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../../src/nip/frames.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAQ,MAAM,CAAC;IACrB,QAAQ,EAAM,MAAM,CAAC;IACrB,SAAS,CAAC,EAAI,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,MAAM,CAAC,EAAQ,SAAS,MAAM,EAAE,CAAC;CAClC;AAED,qBAAa,UAAW,YAAW,QAAQ;aAKvB,GAAG,EAAQ,MAAM;aACjB,MAAM,EAAK,MAAM;aACjB,QAAQ,EAAG,aAAa;aACxB,SAAS,EAAE,MAAM;IAPnC,QAAQ,CAAC,SAAS,mBAAuB;IACzC,QAAQ,CAAC,aAAa,wBAAwB;gBAG5B,GAAG,EAAQ,MAAM,EACjB,MAAM,EAAK,MAAM,EACjB,QAAQ,EAAG,aAAa,EACxB,SAAS,EAAE,MAAM;IAGnC,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAQvC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIjC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU;CAQ3D;AAED,qBAAa,UAAW,YAAW,QAAQ;aAKvB,SAAS,EAAG,MAAM;aAClB,UAAU,EAAE,MAAM;aAClB,MAAM,EAAM,SAAS,MAAM,EAAE;aAC7B,SAAS,EAAG,MAAM;aAClB,SAAS,EAAG,MAAM;IARpC,QAAQ,CAAC,SAAS,mBAAuB;IACzC,QAAQ,CAAC,aAAa,wBAAwB;gBAG5B,SAAS,EAAG,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAM,SAAS,MAAM,EAAE,EAC7B,SAAS,EAAG,MAAM,EAClB,SAAS,EAAG,MAAM;IAGpC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAUjC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU;CAS3D;AAED,qBAAa,WAAY,YAAW,QAAQ;aAKxB,GAAG,EAAQ,MAAM;aACjB,MAAM,CAAC,EAAI,MAAM;aACjB,SAAS,CAAC,EAAE,MAAM;IANpC,QAAQ,CAAC,SAAS,oBAAwB;IAC1C,QAAQ,CAAC,aAAa,wBAAwB;gBAG5B,GAAG,EAAQ,MAAM,EACjB,MAAM,CAAC,EAAI,MAAM,YAAA,EACjB,SAAS,CAAC,EAAE,MAAM,YAAA;IAGpC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAQjC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW;CAO5D"}
|