chore: remove unused desktop app, cloud deployment infra, and monitoring stack

Deletes desktop/ (Electron wrapper), deployments/ (Helm/Kustomize/
Terraform/CI for cloud deploy), and monitoring/ (Prometheus + Grafana
stack) along with DESKTOP.md, DEPLOYMENT.md, docker-compose.full.yml,
their npm scripts, and every dangling reference across README,
ARCHITECTURE, INSTALL, SETUP, docs/, and the repeated per-file
MODULE_GUIDE "Observability" boilerplate comment. The GET /api/metrics
endpoint itself is untouched — it's the dashboard's own route, not
part of the removed monitoring stack.
This commit is contained in:
2026-08-11 12:16:54 +07:00
parent f0ae876472
commit 7357070fb9
307 changed files with 23 additions and 31257 deletions
+1 -1
View File
@@ -467,7 +467,7 @@ The OpenAPI spec is generated from `server/openapi.js` (`createOpenApiSpec()`),
| `GET` | `/api/analytics` | Analytics aggregates for charts/trends |
| `GET` | `/api/metrics` | Prometheus / OpenMetrics exposition (text; v0.0.4) |
**Prometheus metrics (`GET /api/metrics`).** Exposes the dashboard's live counters — `ccam_sessions`/`ccam_agents` by status, `ccam_events_total`, `ccam_tokens_total` by kind, `ccam_websocket_clients`, `ccam_remote_sources` by enabled state, `ccam_process_uptime_seconds`/`ccam_process_resident_memory_bytes`, and `ccam_build_info{version}` — in the Prometheus v0.0.4 text-exposition format for scraping into Prometheus / Grafana (`server/routes/metrics.js`). Values come from the same `server/db.js` prepared statements the REST API uses, so they match the UI; status series are enumerated so a gauge never drops out of the exposition at zero. The route is read-only and, being under `/api`, sits behind both the Host-header (DNS-rebinding) guard and the optional `DASHBOARD_TOKEN` guard: a non-loopback scraper (e.g. Prometheus in Docker via `host.docker.internal`) must be allowlisted with `DASHBOARD_ALLOWED_HOSTS` or it gets `403 EBADHOST`, and must send the token when one is set. A ready-to-run Prometheus + Grafana stack with four auto-provisioned dashboards (default home **CCAM — Overview**) lives in [`monitoring/`](../monitoring/README.md).
**Prometheus metrics (`GET /api/metrics`).** Exposes the dashboard's live counters — `ccam_sessions`/`ccam_agents` by status, `ccam_events_total`, `ccam_tokens_total` by kind, `ccam_websocket_clients`, `ccam_remote_sources` by enabled state, `ccam_process_uptime_seconds`/`ccam_process_resident_memory_bytes`, and `ccam_build_info{version}` — in the Prometheus v0.0.4 text-exposition format for scraping into Prometheus / Grafana (`server/routes/metrics.js`). Values come from the same `server/db.js` prepared statements the REST API uses, so they match the UI; status series are enumerated so a gauge never drops out of the exposition at zero. The route is read-only and, being under `/api`, sits behind both the Host-header (DNS-rebinding) guard and the optional `DASHBOARD_TOKEN` guard: a non-loopback scraper (e.g. Prometheus in Docker via `host.docker.internal`) must be allowlisted with `DASHBOARD_ALLOWED_HOSTS` or it gets `403 EBADHOST`, and must send the token when one is set.
**Data scope (`?sources=`).** `GET /api/sessions`, `/api/events`, `/api/agents`, `/api/stats`, and `/api/analytics` all accept an optional `sources` query param — a comma-separated list of source ids (`local` plus any remote source id, see [Remote Data Sources](#remote-data-sources)) — that narrows the result to sessions with a matching `sessions.source`. It is parsed by `server/lib/source-filter.js` into SQL predicates; `/api/stats` and `/api/analytics` route to the source-scoped aggregates in `server/lib/scoped-stats.js` only when a scope is present, leaving the unscoped fast paths unchanged. `GET /api/sessions/facets` additionally returns a `sources` facet enumerating the known source ids.
-53
View File
@@ -1,53 +0,0 @@
/**
* @file Unit tests for cross-platform monitoring binary URL/path resolution.
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
*/
const { describe, it } = require("node:test");
const assert = require("node:assert/strict");
const {
prometheusUrl,
grafanaUrl,
prometheusArchiveExt,
grafanaArchiveExt,
prometheusPlatform,
prometheusArchiveName,
grafanaArchiveName,
toGrafanaPath,
} = require("../../monitoring/scripts/paths");
describe("monitoring paths", () => {
it("builds official download URLs for the current platform", () => {
const plat = prometheusPlatform();
const promExt = prometheusArchiveExt();
const grafExt = grafanaArchiveExt();
assert.match(
prometheusUrl(),
new RegExp(`${prometheusArchiveName()}\\.${promExt.replace(".", "\\.")}$`)
);
assert.match(
grafanaUrl(),
new RegExp(`grafana-[0-9.]+\\.${plat}\\.${grafExt.replace(".", "\\.")}$`)
);
if (process.platform === "win32") {
assert.equal(promExt, "zip");
assert.equal(grafExt, "zip");
} else {
assert.equal(promExt, "tar.gz");
assert.equal(grafExt, "tar.gz");
}
});
it("normalizes Windows paths for Grafana YAML", () => {
assert.equal(
toGrafanaPath("C:\\ccam\\monitoring\\grafana\\dashboards"),
"C:/ccam/monitoring/grafana/dashboards"
);
});
it("uses consistent archive naming", () => {
assert.match(prometheusArchiveName(), /^prometheus-[0-9.]+\./);
assert.match(grafanaArchiveName(), /^grafana-[0-9.]+\./);
});
});
+1 -2
View File
@@ -17,8 +17,7 @@
* server as anything other than loopback (e.g. Prometheus in Docker via
* `host.docker.internal`) must therefore be allowlisted with
* `DASHBOARD_ALLOWED_HOSTS` (and send the token when one is set), so an instance
* never leaks operational data to an unexpected origin. The turnkey Prometheus +
* Grafana bundle in `monitoring/` documents the exact setup.
* never leaks operational data to an unexpected origin.
*
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
*/