neuralos 3.0.2 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/gybackend.cjs +28 -23
  2. package/package.json +2 -2
package/bin/gybackend.cjs CHANGED
@@ -386599,6 +386599,32 @@ function renderLiveDashboardHtml(state, opts = {}) {
386599
386599
  return renderDashboardHtml(state, { ...opts, live: true, refreshSeconds: 0 });
386600
386600
  }
386601
386601
 
386602
+ // ../../packages/backend/src/services/dashboard/dashboardHttpAuth.ts
386603
+ function isLoopbackAddress(raw) {
386604
+ return /^(127\.|::1|::ffff:127\.)/.test(raw) || raw === "" || raw === "localhost";
386605
+ }
386606
+ function extractDashboardToken(req) {
386607
+ const authz = typeof req.headers.authorization === "string" ? req.headers.authorization : "";
386608
+ const bearer = /^Bearer\s+(.+)$/i.exec(authz)?.[1]?.trim();
386609
+ const headerTok = typeof req.headers["x-access-token"] === "string" ? String(req.headers["x-access-token"]).trim() : "";
386610
+ let queryTok = "";
386611
+ try {
386612
+ queryTok = new URL(req.url ?? "/", "http://localhost").searchParams.get("access_token")?.trim() ?? "";
386613
+ } catch {
386614
+ }
386615
+ return bearer || headerTok || queryTok;
386616
+ }
386617
+ async function dashboardHttpAuthorized(req, verifyToken) {
386618
+ if (isLoopbackAddress(String(req.socket?.remoteAddress ?? ""))) return true;
386619
+ const token = extractDashboardToken(req);
386620
+ if (!token) return false;
386621
+ try {
386622
+ return await verifyToken(token);
386623
+ } catch {
386624
+ return false;
386625
+ }
386626
+ }
386627
+
386602
386628
  // ../../packages/backend/src/services/ResourceMonitorService.ts
386603
386629
  var import_os2 = __toESM(require("os"), 1);
386604
386630
  var DEFAULT_POLL_INTERVAL_MS = 2e3;
@@ -388704,27 +388730,6 @@ async function startGyBackend() {
388704
388730
  gatewayService.broadcastRaw("skills:updated", result.skills);
388705
388731
  gatewayService.broadcastRaw("memory:updated", result.memory);
388706
388732
  };
388707
- const dashboardHttpAuthorized = async (req) => {
388708
- const remote = String(req.socket?.remoteAddress ?? "");
388709
- if (/^(127\.|::1|::ffff:127\.)/.test(remote) || remote === "" || remote === "localhost") {
388710
- return true;
388711
- }
388712
- const authz = typeof req.headers.authorization === "string" ? req.headers.authorization : "";
388713
- const bearer = /^Bearer\s+(.+)$/i.exec(authz)?.[1]?.trim();
388714
- const headerTok = typeof req.headers["x-access-token"] === "string" ? String(req.headers["x-access-token"]).trim() : "";
388715
- let queryTok = "";
388716
- try {
388717
- queryTok = new URL(req.url ?? "/", "http://localhost").searchParams.get("access_token")?.trim() ?? "";
388718
- } catch {
388719
- }
388720
- const token = bearer || headerTok || queryTok;
388721
- if (!token) return false;
388722
- try {
388723
- return await accessTokenService.verifyToken(token);
388724
- } catch {
388725
- return false;
388726
- }
388727
- };
388728
388733
  const wsGatewayControlService = new WebSocketGatewayControlService({
388729
388734
  createAdapter: (host, port, ipFilter) => new WebSocketGatewayAdapter(gatewayService, {
388730
388735
  host,
@@ -388742,7 +388747,7 @@ async function startGyBackend() {
388742
388747
  {
388743
388748
  path: "/dashboard",
388744
388749
  handler: async (req, res) => {
388745
- if (!await dashboardHttpAuthorized(req)) {
388750
+ if (!await dashboardHttpAuthorized(req, (t) => accessTokenService.verifyToken(t))) {
388746
388751
  res.writeHead(401, { "content-type": "text/plain; charset=utf-8" });
388747
388752
  res.end("missing/invalid access token");
388748
388753
  return;
@@ -388760,7 +388765,7 @@ async function startGyBackend() {
388760
388765
  {
388761
388766
  path: "/dashboard/json",
388762
388767
  handler: async (req, res) => {
388763
- if (!await dashboardHttpAuthorized(req)) {
388768
+ if (!await dashboardHttpAuthorized(req, (t) => accessTokenService.verifyToken(t))) {
388764
388769
  res.writeHead(401, { "content-type": "text/plain; charset=utf-8" });
388765
388770
  res.end("missing/invalid access token");
388766
388771
  return;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "neuralos",
3
- "version": "3.0.2",
4
- "description": "neuralOS — the headless AI-native backend for RTerm. run RTerm-as-a-service (AI agent, SSH/WinRM/Serial/local terminals, fleet orchestration, advanced automation, SRE observability, Netdata, AWS APerf, plugin system, governance/audit, Prometheus/OTel metrics export, secrets vault, on-call paging, AI cost budgets, GitOps, cloud inventory, APM/DEM/Infra/ETW ingestion, AgentSpan durable-agent bridge). The RTerm desktop app stays RTerm; neuralOS is the standalone backend daemon. Dual-published as rterm-backend. v3.0.2: live browser dashboard at /dashboard (same-port HTTP + WS push).",
3
+ "version": "3.0.3",
4
+ "description": "neuralOS — the headless AI-native backend for RTerm. run RTerm-as-a-service (AI agent, SSH/WinRM/Serial/local terminals, fleet orchestration, advanced automation, SRE observability, Netdata, AWS APerf, plugin system, governance/audit, Prometheus/OTel metrics export, secrets vault, on-call paging, AI cost budgets, GitOps, cloud inventory, APM/DEM/Infra/ETW ingestion, AgentSpan durable-agent bridge). The RTerm desktop app stays RTerm; neuralOS is the standalone backend daemon. Dual-published as rterm-backend. v3.0.3: fixes /dashboard \"Upgrade Required\" on the desktop app (Electron main now serves it too).",
5
5
  "main": "bin/gybackend.cjs",
6
6
  "bin": {
7
7
  "neuralos": "bin/gybackend.cjs",