@neat.is/core 0.6.3-dev.20260725 → 0.6.3-dev.20260726

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/cli.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  startConnectorPolling,
14
14
  validateConnectorEntry,
15
15
  writeDaemonRecord
16
- } from "./chunk-2BQTX7QX.js";
16
+ } from "./chunk-PWIT35Z4.js";
17
17
  import {
18
18
  buildSearchIndex
19
19
  } from "./chunk-BIY46Q6U.js";
@@ -72,10 +72,10 @@ import {
72
72
  startPersistLoop,
73
73
  startStalenessLoop,
74
74
  upsertConnectorEntry
75
- } from "./chunk-C7TJMXO4.js";
75
+ } from "./chunk-L64CATKE.js";
76
76
  import {
77
77
  startOtelGrpcReceiver
78
- } from "./chunk-TQPDQNUD.js";
78
+ } from "./chunk-7QXN726V.js";
79
79
  import {
80
80
  __dirname,
81
81
  __require,
@@ -83,7 +83,7 @@ import {
83
83
  buildOtelReceiver,
84
84
  listenSteppingOtlp,
85
85
  readAuthEnv
86
- } from "./chunk-H4EAELBI.js";
86
+ } from "./chunk-ZLAZ7PLC.js";
87
87
 
88
88
  // src/cli.ts
89
89
  import path10 from "path";
package/dist/index.cjs CHANGED
@@ -611,6 +611,9 @@ async function buildOtelReceiver(opts) {
611
611
  });
612
612
  app.post("/projects/:project/v1/traces", async (req, reply) => {
613
613
  const project = req.params.project;
614
+ if (opts.isProjectRegistered && !opts.isProjectRegistered(project)) {
615
+ return reply.code(404).send({ error: "project not found", project });
616
+ }
614
617
  const result = await readOtlpBody(req);
615
618
  if (!result.ok) {
616
619
  return reply.code(result.code).send({ error: result.error });
@@ -3455,6 +3458,14 @@ function frontierIdFor(host) {
3455
3458
  function ensureServiceNode(graph, serviceName, env) {
3456
3459
  const id = (0, import_types6.serviceId)(serviceName, env);
3457
3460
  if (graph.hasNode(id)) return id;
3461
+ const wanted = serviceName.toLowerCase();
3462
+ const extractedId = graph.findNode((_nid, attrs) => {
3463
+ if (attrs.type !== import_types6.NodeType.ServiceNode) return false;
3464
+ const svc = attrs;
3465
+ if (svc.discoveredVia === "otel") return false;
3466
+ return typeof svc.name === "string" && svc.name.toLowerCase() === wanted;
3467
+ });
3468
+ if (extractedId) return extractedId;
3458
3469
  const node = {
3459
3470
  id,
3460
3471
  type: import_types6.NodeType.ServiceNode,
@@ -12677,7 +12688,7 @@ function routeSpanToProject(serviceName, projects) {
12677
12688
  if (!serviceName) return DEFAULT_PROJECT;
12678
12689
  for (const entry of projects) {
12679
12690
  if (entry.status === "paused") continue;
12680
- if (entry.name === serviceName) return entry.name;
12691
+ if (entry.name.toLowerCase() === serviceName.toLowerCase()) return entry.name;
12681
12692
  }
12682
12693
  const candidates = [];
12683
12694
  for (const entry of projects) {
@@ -12695,18 +12706,22 @@ function routeSpanToProject(serviceName, projects) {
12695
12706
  return DEFAULT_PROJECT;
12696
12707
  }
12697
12708
  function isTokenPrefix(prefix, full) {
12698
- if (prefix.length >= full.length) return false;
12699
- if (!full.startsWith(prefix)) return false;
12700
- const sep = full.charAt(prefix.length);
12709
+ const p = prefix.toLowerCase();
12710
+ const f = full.toLowerCase();
12711
+ if (p.length >= f.length) return false;
12712
+ if (!f.startsWith(p)) return false;
12713
+ const sep = f.charAt(p.length);
12701
12714
  return sep === "-" || sep === "_";
12702
12715
  }
12703
12716
  function isTokenContained(needle, haystack) {
12704
- if (!haystack.includes(needle)) return false;
12705
- const tokens = haystack.split(/[-_]/);
12706
- return tokens.includes(needle);
12717
+ const n = needle.toLowerCase();
12718
+ const h = haystack.toLowerCase();
12719
+ if (!h.includes(n)) return false;
12720
+ const tokens = h.split(/[-_]/);
12721
+ return tokens.includes(n);
12707
12722
  }
12708
12723
  function serviceNameMatchesProject(serviceName, project) {
12709
- if (serviceName === project) return true;
12724
+ if (serviceName.toLowerCase() === project.toLowerCase()) return true;
12710
12725
  if (isTokenPrefix(project, serviceName)) return true;
12711
12726
  if (isTokenContained(project, serviceName)) return true;
12712
12727
  return false;
@@ -13163,7 +13178,12 @@ async function startDaemon(opts = {}) {
13163
13178
  const slot = await resolveSlotByName(project, span.service, span.traceId);
13164
13179
  if (!slot) return;
13165
13180
  await makeErrorSpanWriter(slot.paths.errorsPath, slot.graph, slot.entry.path)(span);
13166
- }
13181
+ },
13182
+ // #881 — 404 a project-scoped POST for a project this daemon doesn't
13183
+ // host, rather than accepting it and dropping the batch. `slots` covers
13184
+ // active/recovering projects, `bootstrapStatus` the ones still
13185
+ // extracting; a foreign or wrong-cased project name matches neither.
13186
+ isProjectRegistered: (project) => slots.has(project) || bootstrapStatus.has(project)
13167
13187
  });
13168
13188
  otlpAddress = await listenSteppingOtlp(otlpApp, otlpPort, host);
13169
13189
  console.log(`neatd: OTLP listening on ${otlpAddress}/v1/traces`);