@thotischner/observability-mcp 3.6.1 → 3.8.0
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/dist/auth/policy/loader.js +1 -1
- package/dist/auth/rbac.d.ts +1 -1
- package/dist/auth/rbac.js +3 -1
- package/dist/auth/rbac.test.js +5 -3
- package/dist/conformance/inspect-e2e.test.d.ts +1 -0
- package/dist/conformance/inspect-e2e.test.js +104 -0
- package/dist/connectors/loader.js +30 -0
- package/dist/connectors/loader.test.js +11 -0
- package/dist/enrich/rdap.d.ts +40 -0
- package/dist/enrich/rdap.js +122 -0
- package/dist/enrich/rdap.test.d.ts +1 -0
- package/dist/enrich/rdap.test.js +78 -0
- package/dist/enterprise-gate.d.ts +28 -0
- package/dist/enterprise-gate.js +51 -0
- package/dist/enterprise-gate.test.js +21 -1
- package/dist/index.js +296 -8
- package/dist/inspect/enforcer.d.ts +19 -0
- package/dist/inspect/enforcer.js +69 -0
- package/dist/inspect/enforcer.test.d.ts +1 -0
- package/dist/inspect/enforcer.test.js +76 -0
- package/dist/inspect/graph.d.ts +33 -0
- package/dist/inspect/graph.js +0 -0
- package/dist/inspect/graph.test.d.ts +1 -0
- package/dist/inspect/graph.test.js +74 -0
- package/dist/inspect/index.d.ts +8 -0
- package/dist/inspect/index.js +13 -0
- package/dist/inspect/mode.d.ts +20 -0
- package/dist/inspect/mode.js +57 -0
- package/dist/inspect/mode.test.d.ts +1 -0
- package/dist/inspect/mode.test.js +53 -0
- package/dist/inspect/profile-store.d.ts +42 -0
- package/dist/inspect/profile-store.js +139 -0
- package/dist/inspect/profile-store.test.d.ts +1 -0
- package/dist/inspect/profile-store.test.js +82 -0
- package/dist/inspect/profile.d.ts +51 -0
- package/dist/inspect/profile.js +111 -0
- package/dist/inspect/profile.test.d.ts +1 -0
- package/dist/inspect/profile.test.js +96 -0
- package/dist/inspect/recorder.d.ts +42 -0
- package/dist/inspect/recorder.js +72 -0
- package/dist/inspect/recorder.test.d.ts +1 -0
- package/dist/inspect/recorder.test.js +112 -0
- package/dist/inspect/signature.d.ts +32 -0
- package/dist/inspect/signature.js +200 -0
- package/dist/inspect/signature.test.d.ts +1 -0
- package/dist/inspect/signature.test.js +136 -0
- package/dist/inspect/store.d.ts +62 -0
- package/dist/inspect/store.js +76 -0
- package/dist/inspect/store.test.d.ts +1 -0
- package/dist/inspect/store.test.js +78 -0
- package/dist/metrics/self.d.ts +3 -0
- package/dist/metrics/self.js +19 -0
- package/dist/net/egress-policy.js +1 -0
- package/dist/tenancy/context.d.ts +7 -0
- package/dist/tenancy/context.js +15 -0
- package/dist/tenancy/context.test.js +18 -1
- package/dist/tools/enrich-ips.d.ts +6 -2
- package/dist/tools/enrich-ips.js +32 -11
- package/dist/tools/enrich-ips.test.js +55 -11
- package/dist/ui/index.html +742 -0
- package/package.json +3 -2
|
@@ -7,21 +7,21 @@ function parse(result) {
|
|
|
7
7
|
}
|
|
8
8
|
const ds = IpEnrichmentDataset.fromCsv(["1.2.3.0/24,US,Ashburn,AS14618,Example Cloud,true", "203.0.113.5,DE,Berlin,AS3320,Example ISP,false"].join("\n"));
|
|
9
9
|
describe("enrichIpsHandler (R6, issue #415 Gap B)", () => {
|
|
10
|
-
it("returns a clear 'not configured' notice when no dataset is loaded", () => {
|
|
11
|
-
const out = parse(enrichIpsHandler(null, { ips: ["1.2.3.4"] }));
|
|
10
|
+
it("returns a clear 'not configured' notice when no dataset is loaded", async () => {
|
|
11
|
+
const out = parse(await enrichIpsHandler(null, { ips: ["1.2.3.4"] }));
|
|
12
12
|
assert.match(out.error, /not configured/i);
|
|
13
13
|
assert.match(out.error, /OMCP_IP_ENRICH_FILE/);
|
|
14
14
|
});
|
|
15
|
-
it("rejects empty / missing ips", () => {
|
|
16
|
-
assert.match(parse(enrichIpsHandler(ds, { ips: [] })).error, /non-empty array/i);
|
|
17
|
-
assert.match(parse(enrichIpsHandler(ds, {})).error, /non-empty array/i);
|
|
15
|
+
it("rejects empty / missing ips", async () => {
|
|
16
|
+
assert.match(parse(await enrichIpsHandler(ds, { ips: [] })).error, /non-empty array/i);
|
|
17
|
+
assert.match(parse(await enrichIpsHandler(ds, {})).error, /non-empty array/i);
|
|
18
18
|
});
|
|
19
|
-
it("rejects an over-large batch", () => {
|
|
19
|
+
it("rejects an over-large batch", async () => {
|
|
20
20
|
const many = Array.from({ length: 1001 }, (_, i) => `1.2.3.${i % 255}`);
|
|
21
|
-
assert.match(parse(enrichIpsHandler(ds, { ips: many })).error, /Too many IPs/i);
|
|
21
|
+
assert.match(parse(await enrichIpsHandler(ds, { ips: many })).error, /Too many IPs/i);
|
|
22
22
|
});
|
|
23
|
-
it("enriches known IPs and reports found=false for misses + invalid", () => {
|
|
24
|
-
const out = parse(enrichIpsHandler(ds, { ips: ["1.2.3.99", "8.8.8.8", "not-an-ip"] }));
|
|
23
|
+
it("enriches known IPs and reports found=false for misses + invalid", async () => {
|
|
24
|
+
const out = parse(await enrichIpsHandler(ds, { ips: ["1.2.3.99", "8.8.8.8", "not-an-ip"] }));
|
|
25
25
|
assert.equal(out.results.length, 3);
|
|
26
26
|
const matched = out.results.find((r) => r.ip === "1.2.3.99");
|
|
27
27
|
assert.equal(matched.found, true);
|
|
@@ -35,9 +35,9 @@ describe("enrichIpsHandler (R6, issue #415 Gap B)", () => {
|
|
|
35
35
|
assert.deepEqual(out.summary, { total: 3, matched: 1, unmatched: 1, invalid: 1 });
|
|
36
36
|
assert.equal(out.datasetSize, 2);
|
|
37
37
|
});
|
|
38
|
-
it("accepts IPv6 inputs and enriches them (not counted invalid)", () => {
|
|
38
|
+
it("accepts IPv6 inputs and enriches them (not counted invalid)", async () => {
|
|
39
39
|
const ds6 = IpEnrichmentDataset.fromCsv(["2001:db8::/32,US,,AS14618,Example Cloud,true", "1.2.3.0/24,DE,Berlin,AS3320,Example ISP,false"].join("\n"));
|
|
40
|
-
const out = parse(enrichIpsHandler(ds6, { ips: ["2001:db8::1", "2606:4700::1", "1.2.3.9"] }));
|
|
40
|
+
const out = parse(await enrichIpsHandler(ds6, { ips: ["2001:db8::1", "2606:4700::1", "1.2.3.9"] }));
|
|
41
41
|
const v6hit = out.results.find((r) => r.ip === "2001:db8::1");
|
|
42
42
|
assert.equal(v6hit.found, true);
|
|
43
43
|
assert.equal(v6hit.org, "Example Cloud");
|
|
@@ -47,3 +47,47 @@ describe("enrichIpsHandler (R6, issue #415 Gap B)", () => {
|
|
|
47
47
|
assert.deepEqual(out.summary, { total: 3, matched: 2, unmatched: 1, invalid: 0 });
|
|
48
48
|
});
|
|
49
49
|
});
|
|
50
|
+
describe("enrichIpsHandler — optional RDAP fallback (issue #477)", () => {
|
|
51
|
+
// Minimal RdapResolver stub: returns a fixed hit for one IP, null otherwise,
|
|
52
|
+
// and records which IPs it was asked about (to prove CSV-first).
|
|
53
|
+
function rdapStub(hit) {
|
|
54
|
+
const asked = [];
|
|
55
|
+
return {
|
|
56
|
+
asked,
|
|
57
|
+
resolver: { lookup: async (ip) => { asked.push(ip); return hit[ip] ?? null; } },
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
it("with no dataset but RDAP enabled → not 'not configured'; resolves via RDAP", async () => {
|
|
61
|
+
const { resolver } = rdapStub({ "8.8.8.8": { country: "US", org: "Google LLC" } });
|
|
62
|
+
const out = parse(await enrichIpsHandler(null, { ips: ["8.8.8.8", "203.0.113.9"] }, undefined, resolver));
|
|
63
|
+
const hit = out.results.find((r) => r.ip === "8.8.8.8");
|
|
64
|
+
assert.equal(hit.found, true);
|
|
65
|
+
assert.equal(hit.via, "rdap");
|
|
66
|
+
assert.equal(hit.org, "Google LLC");
|
|
67
|
+
assert.equal(out.results.find((r) => r.ip === "203.0.113.9").found, false);
|
|
68
|
+
assert.equal(out.summary.viaRdap, 1);
|
|
69
|
+
assert.equal(out.rdapEnabled, true);
|
|
70
|
+
});
|
|
71
|
+
it("offline dataset is PREFERRED — RDAP is not consulted for a covered IP", async () => {
|
|
72
|
+
const { asked, resolver } = rdapStub({ "1.2.3.9": { country: "XX", org: "should-not-be-used" } });
|
|
73
|
+
const out = parse(await enrichIpsHandler(ds, { ips: ["1.2.3.9"] }, undefined, resolver));
|
|
74
|
+
const hit = out.results.find((r) => r.ip === "1.2.3.9");
|
|
75
|
+
assert.equal(hit.via, "dataset");
|
|
76
|
+
assert.equal(hit.city, "Ashburn"); // from the CSV, not RDAP
|
|
77
|
+
assert.deepEqual(asked, [], "RDAP must not be queried for a dataset-covered IP");
|
|
78
|
+
});
|
|
79
|
+
it("RDAP fills only the gaps the dataset didn't cover", async () => {
|
|
80
|
+
const { asked, resolver } = rdapStub({ "9.9.9.9": { country: "US", org: "Quad9" } });
|
|
81
|
+
const out = parse(await enrichIpsHandler(ds, { ips: ["1.2.3.9", "9.9.9.9"] }, undefined, resolver));
|
|
82
|
+
assert.equal(out.results.find((r) => r.ip === "1.2.3.9").via, "dataset");
|
|
83
|
+
assert.equal(out.results.find((r) => r.ip === "9.9.9.9").via, "rdap");
|
|
84
|
+
assert.deepEqual(asked, ["9.9.9.9"], "RDAP queried only for the uncovered IP");
|
|
85
|
+
assert.equal(out.summary.matched, 2);
|
|
86
|
+
assert.equal(out.summary.viaRdap, 1);
|
|
87
|
+
});
|
|
88
|
+
it("no dataset and no RDAP → still 'not configured', and names both options", async () => {
|
|
89
|
+
const out = parse(await enrichIpsHandler(null, { ips: ["8.8.8.8"] }));
|
|
90
|
+
assert.match(out.error, /not configured/i);
|
|
91
|
+
assert.match(out.error, /OMCP_IP_ENRICH_RDAP/);
|
|
92
|
+
});
|
|
93
|
+
});
|