rigscope 0.0.0-stage → 0.1.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/.next/BUILD_ID +1 -0
- package/.next/app-path-routes-manifest.json +13 -0
- package/.next/build-manifest.json +20 -0
- package/.next/export-marker.json +6 -0
- package/.next/images-manifest.json +68 -0
- package/.next/next-minimal-server.js.nft.json +1 -0
- package/.next/next-server.js.nft.json +1 -0
- package/.next/package.json +1 -0
- package/.next/prerender-manifest.json +297 -0
- package/.next/react-loadable-manifest.json +1 -0
- package/.next/required-server-files.json +369 -0
- package/.next/routes-manifest.json +114 -0
- package/.next/server/app/_global-error/page.js +31 -0
- package/.next/server/app/_global-error/page.js.nft.json +1 -0
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -0
- package/.next/server/app/_global-error.html +1 -0
- package/.next/server/app/_global-error.meta +35 -0
- package/.next/server/app/_global-error.rsc +18 -0
- package/.next/server/app/_global-error.segments/_full.segment.rsc +18 -0
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +24 -0
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +3 -0
- package/.next/server/app/_not-found/page.js +1 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
- package/.next/server/app/_not-found.html +1 -0
- package/.next/server/app/_not-found.meta +35 -0
- package/.next/server/app/_not-found.rsc +24 -0
- package/.next/server/app/_not-found.segments/_full.segment.rsc +24 -0
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +30 -0
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/administration/page.js +1 -0
- package/.next/server/app/administration/page.js.nft.json +1 -0
- package/.next/server/app/administration/page_client-reference-manifest.js +1 -0
- package/.next/server/app/administration.html +1 -0
- package/.next/server/app/administration.meta +34 -0
- package/.next/server/app/administration.rsc +29 -0
- package/.next/server/app/administration.segments/_full.segment.rsc +29 -0
- package/.next/server/app/administration.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/administration.segments/administration/__PAGE__.segment.rsc +35 -0
- package/.next/server/app/alerts/page.js +1 -0
- package/.next/server/app/alerts/page.js.nft.json +1 -0
- package/.next/server/app/alerts/page_client-reference-manifest.js +1 -0
- package/.next/server/app/alerts.html +1 -0
- package/.next/server/app/alerts.meta +34 -0
- package/.next/server/app/alerts.rsc +28 -0
- package/.next/server/app/alerts.segments/_full.segment.rsc +28 -0
- package/.next/server/app/alerts.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/alerts.segments/alerts/__PAGE__.segment.rsc +34 -0
- package/.next/server/app/connections/page.js +1 -0
- package/.next/server/app/connections/page.js.nft.json +1 -0
- package/.next/server/app/connections/page_client-reference-manifest.js +1 -0
- package/.next/server/app/connections.html +1 -0
- package/.next/server/app/connections.meta +34 -0
- package/.next/server/app/connections.rsc +29 -0
- package/.next/server/app/connections.segments/_full.segment.rsc +29 -0
- package/.next/server/app/connections.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/connections.segments/connections/__PAGE__.segment.rsc +35 -0
- package/.next/server/app/history/page.js +2 -0
- package/.next/server/app/history/page.js.nft.json +1 -0
- package/.next/server/app/history/page_client-reference-manifest.js +1 -0
- package/.next/server/app/history.html +1 -0
- package/.next/server/app/history.meta +34 -0
- package/.next/server/app/history.rsc +33 -0
- package/.next/server/app/history.segments/_full.segment.rsc +33 -0
- package/.next/server/app/history.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/history.segments/history/__PAGE__.segment.rsc +37 -0
- package/.next/server/app/icon.svg/route.js +1 -0
- package/.next/server/app/icon.svg/route.js.nft.json +1 -0
- package/.next/server/app/icon.svg.body +1 -0
- package/.next/server/app/icon.svg.meta +1 -0
- package/.next/server/app/index.html +1 -0
- package/.next/server/app/index.meta +29 -0
- package/.next/server/app/index.rsc +26 -0
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +31 -0
- package/.next/server/app/index.segments/_full.segment.rsc +26 -0
- package/.next/server/app/index.segments/_tree.segment.rsc +3 -0
- package/.next/server/app/login/page.js +1 -0
- package/.next/server/app/login/page.js.nft.json +1 -0
- package/.next/server/app/login/page_client-reference-manifest.js +1 -0
- package/.next/server/app/login.html +1 -0
- package/.next/server/app/login.meta +34 -0
- package/.next/server/app/login.rsc +26 -0
- package/.next/server/app/login.segments/_full.segment.rsc +26 -0
- package/.next/server/app/login.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +32 -0
- package/.next/server/app/machines/[machineId]/page.js +1 -0
- package/.next/server/app/machines/[machineId]/page.js.nft.json +1 -0
- package/.next/server/app/machines/[machineId]/page_client-reference-manifest.js +1 -0
- package/.next/server/app/page.js +1 -0
- package/.next/server/app/page.js.nft.json +1 -0
- package/.next/server/app/page_client-reference-manifest.js +1 -0
- package/.next/server/app/processes/page.js +2 -0
- package/.next/server/app/processes/page.js.nft.json +1 -0
- package/.next/server/app/processes/page_client-reference-manifest.js +1 -0
- package/.next/server/app/processes.html +1 -0
- package/.next/server/app/processes.meta +34 -0
- package/.next/server/app/processes.rsc +30 -0
- package/.next/server/app/processes.segments/_full.segment.rsc +30 -0
- package/.next/server/app/processes.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/processes.segments/processes/__PAGE__.segment.rsc +36 -0
- package/.next/server/app-paths-manifest.json +13 -0
- package/.next/server/chunks/161.js +1 -0
- package/.next/server/chunks/168.js +1 -0
- package/.next/server/chunks/266.js +68 -0
- package/.next/server/chunks/430.js +116 -0
- package/.next/server/chunks/721.js +1 -0
- package/.next/server/chunks/751.js +1 -0
- package/.next/server/chunks/877.js +1 -0
- package/.next/server/chunks/894.js +2 -0
- package/.next/server/functions-config-manifest.json +4 -0
- package/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/.next/server/middleware-build-manifest.js +1 -0
- package/.next/server/middleware-manifest.json +6 -0
- package/.next/server/middleware-react-loadable-manifest.js +1 -0
- package/.next/server/next-font-manifest.js +1 -0
- package/.next/server/next-font-manifest.json +1 -0
- package/.next/server/pages/404.html +1 -0
- package/.next/server/pages/500.html +1 -0
- package/.next/server/pages-manifest.json +4 -0
- package/.next/server/prefetch-hints.json +123 -0
- package/.next/server/preview-props.json +5 -0
- package/.next/server/server-reference-manifest.js +1 -0
- package/.next/server/server-reference-manifest.json +1 -0
- package/.next/server/webpack-runtime.js +1 -0
- package/.next/static/DZKWF9ur7H5wI0c7RAhdq/_buildManifest.js +1 -0
- package/.next/static/DZKWF9ur7H5wI0c7RAhdq/_ssgManifest.js +1 -0
- package/.next/static/chunks/103-c47318242b24e9ac.js +1 -0
- package/.next/static/chunks/157-0d36ebf66af048ac.js +1 -0
- package/.next/static/chunks/227-417939c480f50747.js +1 -0
- package/.next/static/chunks/408-18819c6490a5f8d3.js +1 -0
- package/.next/static/chunks/4bd1b696-c7408084347438ae.js +1 -0
- package/.next/static/chunks/794-ceeb732a1a81bc27.js +52 -0
- package/.next/static/chunks/939-2600d7c8e583d5ef.js +1 -0
- package/.next/static/chunks/app/_global-error/page-aba28f88d5781771.js +1 -0
- package/.next/static/chunks/app/_not-found/page-a2a510233e4836e2.js +1 -0
- package/.next/static/chunks/app/administration/page-4b16b19bb6a39c36.js +1 -0
- package/.next/static/chunks/app/alerts/page-fe0e877778c60af8.js +1 -0
- package/.next/static/chunks/app/connections/page-99cd54d6929b3f1f.js +1 -0
- package/.next/static/chunks/app/history/page-3fa5846eca26b7f7.js +3 -0
- package/.next/static/chunks/app/layout-4feff677c4071745.js +1 -0
- package/.next/static/chunks/app/login/page-c57e12dbe5146737.js +1 -0
- package/.next/static/chunks/app/machines/[machineId]/page-a5aa1d8676272f38.js +1 -0
- package/.next/static/chunks/app/page-1ae9fc94c897785b.js +1 -0
- package/.next/static/chunks/app/processes/page-e471ed23a1d5632f.js +3 -0
- package/.next/static/chunks/framework-ea4f97ca039bd777.js +1 -0
- package/.next/static/chunks/main-a458d32948147b84.js +5 -0
- package/.next/static/chunks/main-app-f92328c8950d2e53.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-aba28f88d5781771.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-aba28f88d5781771.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/global-error-43cbaa3aa1576eb4.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-aba28f88d5781771.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-aba28f88d5781771.js +1 -0
- package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/.next/static/chunks/webpack-9ca43f4ce1bb8938.js +1 -0
- package/.next/static/css/e41ccbccc3afaae5.css +1 -0
- package/ARCHITECTURE.md +279 -0
- package/CHANGELOG.md +25 -0
- package/DESIGN.md +299 -0
- package/LICENSE +21 -0
- package/README.md +157 -2
- package/SECURITY.md +12 -0
- package/THIRD_PARTY_NOTICES.md +8847 -0
- package/bin/rigscope.cjs +6 -0
- package/dist/cli.cjs +9075 -0
- package/dist/collector.cjs +5671 -0
- package/dist/hub.cjs +8355 -0
- package/dist/ops.cjs +4972 -0
- package/dist/system.cjs +4333 -0
- package/docs/bottlenecks.md +62 -0
- package/docs/development.md +46 -0
- package/docs/exports.md +39 -0
- package/docs/installation.md +477 -0
- package/docs/operations.md +515 -0
- package/docs/releasing.md +152 -0
- package/docs/scale-acceptance.json +412 -0
- package/docs/scale-validation.json +1898 -0
- package/docs/scale-validation.md +263 -0
- package/next.config.js +38 -0
- package/package.json +109 -4
- package/packaging/README.md +5 -0
- package/packaging/collector.env.example +24 -0
- package/packaging/hub.env.example +31 -0
- package/packaging/system/90-rigscope-rapl.rules +7 -0
- package/packaging/system/README.md +5 -0
- package/packaging/system/rigscope-collector.service.example +53 -0
- package/packaging/system/rigscope-hub.service.example +50 -0
- package/packaging/system/rigscope-rapl.sysusers +5 -0
- package/packaging/system/rigscope.sysusers +7 -0
package/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# Rigscope architecture
|
|
2
|
+
|
|
3
|
+
Rigscope has one hub application process and one collector per monitored machine. This is a custom-server deployment with a production Next.js UI, not `next start` or a serverless application.
|
|
4
|
+
|
|
5
|
+
## Topology and ownership
|
|
6
|
+
|
|
7
|
+
- Install one collector per monitored machine.
|
|
8
|
+
- Each collector opens one outbound connection to each configured hub.
|
|
9
|
+
- A hub receives many collector connections and serves many authenticated browsers.
|
|
10
|
+
- Browsers connect to a hub; they need no direct access to collectors.
|
|
11
|
+
- Monitor the hub's machine by installing a collector there using the same protocol.
|
|
12
|
+
- Each hub owns enrollment, permissions, retention, alerts, and users independently.
|
|
13
|
+
Two hubs do not imply replicated databases or an automatic failover cluster.
|
|
14
|
+
- Multiple destinations are supported from the first collector implementation. Hub
|
|
15
|
+
federation, automatic discovery, and clustered hub deployments are separate requirements.
|
|
16
|
+
|
|
17
|
+
Only collector-to-hub and browser-to-hub reachability is necessary. LAN, Tailscale,
|
|
18
|
+
and ordinary routed networks use the same protocol. No collector-to-collector links
|
|
19
|
+
or inbound collector ports are required.
|
|
20
|
+
|
|
21
|
+
## Transport choices
|
|
22
|
+
|
|
23
|
+
| Link / operation | Transport | Reason |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| Collector ↔ hub | WebSocket over TLS (`wss://`) | One outbound session carries telemetry, acknowledgments, capabilities, and detail requests in both directions. |
|
|
26
|
+
| Hub → browser, live updates | SSE over HTTPS | Predominantly one-way updates; EventSource provides reconnects and event IDs. |
|
|
27
|
+
| Browser → hub, queries/actions | HTTPS JSON requests | Normal request/response semantics for history, settings, authentication, and explicit actions. |
|
|
28
|
+
| Collector enrollment | HTTPS JSON request | Exchange a short-lived enrollment token for a credential specific to that hub connection. |
|
|
29
|
+
|
|
30
|
+
WebSocket keeps acknowledgments and on-demand detail requests on the collector's existing outbound connection. Browser SSE and JSON requests keep live updates separate from explicit queries. Bounded JSON frames have no automatic transport fallback.
|
|
31
|
+
|
|
32
|
+
## Runtime and module boundaries
|
|
33
|
+
|
|
34
|
+
Keep TypeScript/Node and Next.js, with two executable roles: `collector` and `hub`.
|
|
35
|
+
The hub has one explicit, long-running Node entry point that owns its HTTP server,
|
|
36
|
+
WebSocket upgrades, application services, and background jobs. It delegates UI requests to
|
|
37
|
+
Next.js. This preserves one hub application process/listener; a TLS proxy is optional
|
|
38
|
+
infrastructure. Collection belongs to the collector and continues without a browser.
|
|
39
|
+
|
|
40
|
+
Transport handlers receive services from the composition root. Do not assume a `globalThis`
|
|
41
|
+
object is shared between Next.js bundles or let route requests start monitoring loops.
|
|
42
|
+
This is a custom-server deployment, not unchanged `next start` or a serverless deployment.
|
|
43
|
+
The entry point has its own runtime bundle. Production ships `.next` with `dist/*.cjs`; development uses `.next-dev`. Collector upgrades go to `/api/collector/connect`; framework upgrades reach Next.js.
|
|
44
|
+
|
|
45
|
+
Module layout (responsibilities; consult the source tree for exact paths):
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
collector/
|
|
49
|
+
main.ts # lifecycle and local configuration
|
|
50
|
+
sampling/ # OS metrics, capabilities, monotonic rate calculation
|
|
51
|
+
destinations/ # independent delivery session/outbox per hub
|
|
52
|
+
src/
|
|
53
|
+
contracts/ # wire schemas, units, identifiers
|
|
54
|
+
hub/
|
|
55
|
+
main.ts # composition root; HTTP + upgrades + Next.js
|
|
56
|
+
enrollment/ # credentials and hub-local machine mapping
|
|
57
|
+
telemetry/ # validation, persistence, latest state, freshness
|
|
58
|
+
subscriptions/ # browser interests -> expiring detail requests
|
|
59
|
+
history/ # SQLite batches, queries, retention, rollups
|
|
60
|
+
alerts/ # incident lifecycle and notifications
|
|
61
|
+
transport/ # WebSocket, SSE, and HTTP handlers
|
|
62
|
+
app/ # fleet and machine-scoped UI
|
|
63
|
+
components/ # existing visual system
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Keep substantial behavior behind small module interfaces. Telemetry accepts batches,
|
|
67
|
+
returns state/history, and provides subscriptions; callers do not manage its deduplication
|
|
68
|
+
or freshness. Destination delivery hides reconnects/acks/outboxes from sampling. Sampling
|
|
69
|
+
hides OS/tool differences. Do not add generic interfaces for hypothetical implementations;
|
|
70
|
+
wire contracts are a real process boundary already.
|
|
71
|
+
|
|
72
|
+
### Installation and component lifecycle
|
|
73
|
+
|
|
74
|
+
One release contains the hub, collector, UI and administration tools. The install
|
|
75
|
+
role is an initial preset; version 2 configuration records independent hub and
|
|
76
|
+
collector enablement. Version 1 roles are mapped in memory on read and migrated
|
|
77
|
+
on an explicit mutation. Read-only status never rewrites configuration or units.
|
|
78
|
+
|
|
79
|
+
User installations have separate hashed hub and collector systemd units, each
|
|
80
|
+
running `rigscope run hub|collector` with its own supervisor lease. System scope
|
|
81
|
+
uses separate dedicated accounts and hardened units. Neither service depends on
|
|
82
|
+
the other. Each retains its settings, credentials and data when disabled; a
|
|
83
|
+
collector can continue sending to remote hubs while its local hub is disabled.
|
|
84
|
+
An unconfigured collector reports Awaiting connection and stays dormant.
|
|
85
|
+
|
|
86
|
+
The configuration module owns presets, migration and component setup. The service
|
|
87
|
+
module owns systemd control and component service registration. The lifecycle
|
|
88
|
+
module starts and verifies selected components. Upgrade and rollback coordinate
|
|
89
|
+
one shared runtime, hold both component leases, back up hub storage and restore
|
|
90
|
+
the exact previous activity and startup settings. Uninstall removes both units,
|
|
91
|
+
launcher and runtime copies while retaining application data.
|
|
92
|
+
|
|
93
|
+
Automatic colocated pairing uses bootstrap configuration only before the first
|
|
94
|
+
hub start. Once SQLite owns the registry, pairing uses that registry and the
|
|
95
|
+
normal enrollment endpoint to update a live hub without restarting it. Existing
|
|
96
|
+
collector destinations are preserved. Explicit `connect` also supports a
|
|
97
|
+
one-time grant from another machine's hub. The [installation guide](docs/installation.md) describes component commands and hub-first setup.
|
|
98
|
+
|
|
99
|
+
The implemented coordination boundaries are:
|
|
100
|
+
|
|
101
|
+
- `src/live/machine-selection.ts` resolves route, authorized Fleet and remembered
|
|
102
|
+
selection with view-specific fallbacks, and coordinates navigation and persistence.
|
|
103
|
+
Views consume the selection; explicit missing Machines retain their access outcome.
|
|
104
|
+
- `src/hub/sample-ingestion.ts` authenticates Sample identity against the current
|
|
105
|
+
Collector session, commits through `TelemetryStore`, then publishes eligible live
|
|
106
|
+
Samples and Incident observations only while that session remains current. It also
|
|
107
|
+
restores persisted metrics, cadence, inventory and metadata at startup without
|
|
108
|
+
marking a Collector connected. Transport formats acknowledgments from its outcomes.
|
|
109
|
+
- `collector/destinations/connection.ts` owns each Hub connection's sharing policy,
|
|
110
|
+
cadence, recovered queue sanitation, inventory and durable append-before-send path.
|
|
111
|
+
Collector runtime fans shared Samples out to these connections. Sampling, GPU
|
|
112
|
+
polling, aggregate disk budgets and cross-Hub Detail scheduling remain shared.
|
|
113
|
+
Recovery applies privacy filtering without reapplying capture-time cadence.
|
|
114
|
+
|
|
115
|
+
## Identity, enrollment, and messages
|
|
116
|
+
|
|
117
|
+
Generate a persistent collector installation ID locally. Enroll it separately with each hub,
|
|
118
|
+
which maps the authenticated collector to a hub-local machine ID. Addresses/hostnames are
|
|
119
|
+
metadata. Reinstall/replacement needs explicit enrollment or administrator reassociation;
|
|
120
|
+
cloned installations must generate new identities.
|
|
121
|
+
|
|
122
|
+
Each hub connection has an independent credential and local sharing policy. Verify the
|
|
123
|
+
hub's TLS certificate using ordinary certificate trust. Send credentials in an authorization
|
|
124
|
+
header, not a URL. Remote connections require TLS; loopback-only development may explicitly
|
|
125
|
+
use plaintext. Authenticate first and reject conflicting claimed collector identities.
|
|
126
|
+
|
|
127
|
+
JSON message families:
|
|
128
|
+
|
|
129
|
+
- `hello` / `welcome`: capabilities, inventory, hub/session identity.
|
|
130
|
+
- `samples` / `ack`: bounded batches; identify exactly which sample IDs were durably accepted
|
|
131
|
+
or permanently rejected.
|
|
132
|
+
- `detail.subscribe` / `detail.cancel` / `detail.result`: scoped, temporary monitoring detail.
|
|
133
|
+
- `heartbeat`, `collector.status`, `gap`: connection liveness, collection errors, and
|
|
134
|
+
monitoring intervals lost to delivery limits.
|
|
135
|
+
|
|
136
|
+
Sample fields: `collectorId`, `runId`, `sequence`, `bootId`, `capturedAt`,
|
|
137
|
+
`kind`, and validated `payload`. `runId` changes on collector restart; `bootId` identifies
|
|
138
|
+
an OS boot. `(collectorId, runId, sequence)` is unique, with sequence increasing across
|
|
139
|
+
sample kinds within a run. Each hub assigns `receivedAt` and its own browser-stream cursor.
|
|
140
|
+
Use stable resource IDs where possible, e.g. GPU UUID, not display order. Define units/CPU
|
|
141
|
+
normalization and calculate rates from local monotonic elapsed time.
|
|
142
|
+
|
|
143
|
+
Separate inventory, periodic metrics, and process detail. Unsupported/failed metrics have
|
|
144
|
+
explicit status and absent values, never successful zeroes. Process detail is live/on
|
|
145
|
+
demand and is not persisted by default.
|
|
146
|
+
|
|
147
|
+
## Multiple hubs and subscription policy
|
|
148
|
+
|
|
149
|
+
Collect each metric once at the fastest locally permitted requested cadence, then fan it
|
|
150
|
+
out to authorized connections. Apply per-destination field filters and cadence before
|
|
151
|
+
queueing/transmission. Omit process arguments and environment variables by default. Hubs
|
|
152
|
+
cannot install destinations, change another destination's policy, or exceed local budgets.
|
|
153
|
+
If a destination's sharing policy is reduced, cancel disallowed subscriptions and purge
|
|
154
|
+
now-forbidden fields from its pending queue before further transmission.
|
|
155
|
+
|
|
156
|
+
Each destination owns its session, bounded queue, acknowledgment state, and reconnect
|
|
157
|
+
schedule. An offline hub must not block a healthy hub or sampling. Set a configurable
|
|
158
|
+
destination count and global resource budget as well as per-destination limits.
|
|
159
|
+
|
|
160
|
+
Example: A needs GPU summaries; B needs summaries and has someone viewing Processes. Share
|
|
161
|
+
one GPU collection pass, deliver process detail only to B, and stop extra scans when its
|
|
162
|
+
subscription expires. A's subscription must not authorize sensitive delivery to B.
|
|
163
|
+
|
|
164
|
+
## Failure, delivery, and overload
|
|
165
|
+
|
|
166
|
+
- WebSocket ordering applies within a connection, not across reconnects. Use heartbeats,
|
|
167
|
+
idle deadlines, and exponential reconnect backoff with jitter.
|
|
168
|
+
- Periodic metrics use at-least-once delivery within the retention budget. Retry retained samples until acked;
|
|
169
|
+
deduplicate in the hub transaction. Ack after durable commit, not socket receipt. Reject
|
|
170
|
+
invalid records explicitly so bad samples cannot retry forever. Process results are
|
|
171
|
+
transient and request-scoped.
|
|
172
|
+
- Use disk-backed per-hub outboxes for periodic metrics to recover across collector restarts.
|
|
173
|
+
Bound age/bytes per destination and total disk usage. Default caps: 10 minutes / 64 MiB
|
|
174
|
+
per destination, whichever comes first; measure before finalizing. Evict oldest pending
|
|
175
|
+
telemetry at the cap and retain a bounded, coalesced gap notice. Bound the in-flight
|
|
176
|
+
window too. Do not spool sensitive process detail by default.
|
|
177
|
+
- Prioritize fresh metrics over rate-limited backfill. Backfill fills history but cannot
|
|
178
|
+
replace newer live state or trigger an old incident as if it just happened.
|
|
179
|
+
- Bound frames, ingestion rates, outstanding requests, and browser buffers. WebSocket does
|
|
180
|
+
not supply application delivery guarantees. Coalesce metric updates for a slow browser
|
|
181
|
+
or disconnect/resynchronize it; refetch incident state after gaps.
|
|
182
|
+
- Track connection health separately from sample freshness: a connected collector can
|
|
183
|
+
have broken GPU collection. Use expected cadence and receipt time for liveness; retain
|
|
184
|
+
capture time and flag clock skew rather than trusting remote wall clocks.
|
|
185
|
+
- Removing a destination stops delivery and purges its credential/outbox. Hub revocation
|
|
186
|
+
terminates existing sessions as well as rejecting new ones.
|
|
187
|
+
|
|
188
|
+
## Browser flow
|
|
189
|
+
|
|
190
|
+
Use one authorized, multiplexed SSE stream per open app tab for its machines/event types,
|
|
191
|
+
not one per chart or machine. Prefer HTTP/2 at the TLS proxy because HTTP/1.1 browsers limit
|
|
192
|
+
concurrent SSE connections per origin. Disable proxy buffering for streams and configure
|
|
193
|
+
WebSocket upgrades/idle timeouts end to end.
|
|
194
|
+
|
|
195
|
+
Authenticate with same-origin secure, HttpOnly session cookies. Authorize scope on connect,
|
|
196
|
+
replay, and permission changes; protect mutations against CSRF. Filter before transmission.
|
|
197
|
+
Establish a consistent initial subscription/snapshot boundary, then emit updates. Provide
|
|
198
|
+
event IDs and bounded replay. Expired cursors or a previous hub run cause a reset/fresh
|
|
199
|
+
snapshot. EventSource reconnects do not themselves provide durable replay. History queries
|
|
200
|
+
use HTTPS with a point/result budget and suitable rollups.
|
|
201
|
+
|
|
202
|
+
Opening an authorized detail view creates/renews a bounded lease over the collector's
|
|
203
|
+
existing WebSocket. The hub combines equivalent viewer interests; the collector combines
|
|
204
|
+
compatible interests across hubs while preserving delivery permissions. Expire leases
|
|
205
|
+
using local monotonic TTLs. Browser disconnect, hub disconnect, or renewal failure releases
|
|
206
|
+
extra work promptly. Requests must fit local policy and reported capabilities.
|
|
207
|
+
|
|
208
|
+
## Storage and scale
|
|
209
|
+
|
|
210
|
+
Each hub owns a SQLite database, one bounded write queue, batched writes, retention, and
|
|
211
|
+
rollups that preserve min/max. Never scan the OS or write telemetry once per browser.
|
|
212
|
+
Bound query/transaction work. Measure event loop delay during ingestion, history queries,
|
|
213
|
+
retention and rendering; move synchronous database work to a worker thread if needed.
|
|
214
|
+
|
|
215
|
+
One hub application instance owns connection registry, leases, latest state, and bounded
|
|
216
|
+
browser replay. Many connections do not require multiple backend replicas. Replicas later
|
|
217
|
+
need explicit session routing, pub/sub, shared storage, and background-job ownership.
|
|
218
|
+
|
|
219
|
+
Historical planning envelope: 1–50 machines with multiple viewers, not a measured capacity
|
|
220
|
+
claim. There is no fixed machine-count limit. The concurrent collector socket budget
|
|
221
|
+
defaults to 100 and is configurable with `HUB_MAX_COLLECTOR_CONNECTIONS`; it is a
|
|
222
|
+
deployment resource budget, not enrollment capacity. Benchmark representative payload
|
|
223
|
+
sizes, process counts, subscriptions, viewers, history queries and host resources.
|
|
224
|
+
Observe queue depth, stream count, active leases,
|
|
225
|
+
ingestion lag, dropped samples, memory, and event loop delay.
|
|
226
|
+
|
|
227
|
+
## Future actions
|
|
228
|
+
|
|
229
|
+
The release is read-only. Future structured actions travel browser HTTPS →
|
|
230
|
+
hub authorization/audit → collector WebSocket → result → hub → browser SSE. Each destination
|
|
231
|
+
has an explicit action policy, default denied. Read-only hubs may request allowed monitoring
|
|
232
|
+
detail. Initially allow at most one mutating hub per collector to avoid conflicting control.
|
|
233
|
+
|
|
234
|
+
Actions need request IDs, deadlines, handling of ambiguous outcomes after connection loss,
|
|
235
|
+
and execution-time target validation (machine/boot/PID/start identity for processes).
|
|
236
|
+
Do not apply telemetry retry behavior to destructive actions. Specify action semantics
|
|
237
|
+
separately before implementing kill/renice or service restarts.
|
|
238
|
+
|
|
239
|
+
## Terminology
|
|
240
|
+
|
|
241
|
+
**Machine**:
|
|
242
|
+
A physical server or virtual machine whose operating system and workloads are monitored.
|
|
243
|
+
_Avoid_: Node (when it means the monitored machine)
|
|
244
|
+
|
|
245
|
+
**Collector**:
|
|
246
|
+
The background service installed on a machine to gather its monitoring information and report it to configured hubs.
|
|
247
|
+
_Avoid_: Agent, AI agent, sensor, exporter (for this service)
|
|
248
|
+
|
|
249
|
+
**Hub**:
|
|
250
|
+
An independently operated monitoring service that receives information from collectors and makes it available to its users.
|
|
251
|
+
_Avoid_: Primary (unless an explicit primary relationship exists)
|
|
252
|
+
|
|
253
|
+
**Hub connection**:
|
|
254
|
+
A collector's independently configured relationship with one hub, including what information that hub may receive and what requests it may make.
|
|
255
|
+
_Avoid_: Replica, mirror (independent hubs do not imply replicated state)
|
|
256
|
+
|
|
257
|
+
**Fleet**:
|
|
258
|
+
The collection of machines a user can view through a particular hub.
|
|
259
|
+
|
|
260
|
+
**Browser session**:
|
|
261
|
+
A user's authenticated access to one independently operated hub.
|
|
262
|
+
|
|
263
|
+
**Machine scope**:
|
|
264
|
+
The set of machines a user is permitted to view through a hub. An empty scope grants no machine access.
|
|
265
|
+
|
|
266
|
+
**Sample**:
|
|
267
|
+
A measurement of a machine or resource at a particular time.
|
|
268
|
+
|
|
269
|
+
**Capability**:
|
|
270
|
+
A category of monitoring information or permitted operation that a collector can provide for a particular hub connection.
|
|
271
|
+
|
|
272
|
+
**Detail subscription**:
|
|
273
|
+
A temporary request for more detailed monitoring information about selected resources.
|
|
274
|
+
|
|
275
|
+
**Incident**:
|
|
276
|
+
A tracked occurrence of an alert condition, including its active and resolved states.
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
See [operations](docs/operations.md) for persistence, upgrade and recovery guarantees.
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Release notes
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
Initial public release of Rigscope, a self-hosted Linux system and process monitor.
|
|
6
|
+
|
|
7
|
+
- Fleet and machine views with CPU, memory, swap, GPU, disk and network readings.
|
|
8
|
+
- Durable History, per-core charts, live process inspection and CSV/JSON exports.
|
|
9
|
+
- Threshold and availability alerts, HTTPS webhooks, users and machine scopes.
|
|
10
|
+
- Outbound collectors with independent sharing and durable retry queues for up to
|
|
11
|
+
eight hubs per collector.
|
|
12
|
+
- Managed user installation, independent hub/collector services, enrollment,
|
|
13
|
+
diagnostics, verified upgrades, rollback and offline password recovery.
|
|
14
|
+
- Optional system installation with dedicated unprivileged service accounts and
|
|
15
|
+
narrowly scoped CPU package-energy access.
|
|
16
|
+
|
|
17
|
+
Requires Linux and Node.js 26+. Background user installation requires systemd.
|
|
18
|
+
NVIDIA and available AMD GPU counters are supported; Intel sensors are partial.
|
|
19
|
+
Missing or inaccessible readings remain unavailable. Remote process mutation,
|
|
20
|
+
hub federation and clustering are outside this release.
|
|
21
|
+
|
|
22
|
+
See [installation](docs/installation.md) for hardware limits and
|
|
23
|
+
[scale validation](docs/scale-validation.md) for measured synthetic workloads.
|
|
24
|
+
Internal configuration, database and wire-protocol revisions are independent of
|
|
25
|
+
the application version.
|
package/DESIGN.md
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Rigscope
|
|
3
|
+
description: A calm remote monitoring console with clear hierarchy, useful density, and coherent dark/light themes.
|
|
4
|
+
colors:
|
|
5
|
+
background: "#1a1b1e"
|
|
6
|
+
card: "#26272b"
|
|
7
|
+
card-strong: "#2d2e33"
|
|
8
|
+
border: "#3a3b3f"
|
|
9
|
+
foreground: "#e4e5e8"
|
|
10
|
+
muted-foreground: "#a2a4a9"
|
|
11
|
+
accent: "#3584e4"
|
|
12
|
+
accent-foreground: "#ffffff"
|
|
13
|
+
selected: "#1e3a5c"
|
|
14
|
+
ok: "#3db84a"
|
|
15
|
+
ok-soft: "rgba(61, 184, 74, 0.15)"
|
|
16
|
+
warn: "#e5a83b"
|
|
17
|
+
warn-soft: "rgba(229, 168, 59, 0.15)"
|
|
18
|
+
crit: "#e05e5e"
|
|
19
|
+
crit-soft: "rgba(224, 94, 94, 0.15)"
|
|
20
|
+
cpu: "#3584e4"
|
|
21
|
+
mem: "#4ec289"
|
|
22
|
+
swap: "#d8a23a"
|
|
23
|
+
scrollbar: "#3a3b3f"
|
|
24
|
+
typography:
|
|
25
|
+
page-title:
|
|
26
|
+
fontFamily: "system-ui, ui-sans-serif, 'Noto Sans', 'Inter', sans-serif"
|
|
27
|
+
fontSize: "1.125rem"
|
|
28
|
+
fontWeight: 600
|
|
29
|
+
letterSpacing: "-0.025em"
|
|
30
|
+
panel-title:
|
|
31
|
+
fontFamily: "system-ui, ui-sans-serif, 'Noto Sans', 'Inter', sans-serif"
|
|
32
|
+
fontSize: "0.875rem"
|
|
33
|
+
fontWeight: 500
|
|
34
|
+
letterSpacing: "-0.025em"
|
|
35
|
+
nav:
|
|
36
|
+
fontFamily: "system-ui, ui-sans-serif, 'Noto Sans', 'Inter', sans-serif"
|
|
37
|
+
fontSize: "0.875rem"
|
|
38
|
+
fontWeight: 400
|
|
39
|
+
letterSpacing: "-0.025em"
|
|
40
|
+
support:
|
|
41
|
+
fontFamily: "system-ui, ui-sans-serif, 'Noto Sans', 'Inter', sans-serif"
|
|
42
|
+
fontSize: "0.75rem"
|
|
43
|
+
fontWeight: 400
|
|
44
|
+
lineHeight: 1.5
|
|
45
|
+
data:
|
|
46
|
+
fontFamily: "system-ui, ui-sans-serif, 'Noto Sans', 'Inter', sans-serif"
|
|
47
|
+
fontSize: "1.25rem"
|
|
48
|
+
fontWeight: 600
|
|
49
|
+
fontFeature: "tabular-nums"
|
|
50
|
+
letterSpacing: "-0.025em"
|
|
51
|
+
rounded:
|
|
52
|
+
panel: "12px"
|
|
53
|
+
row: "8px"
|
|
54
|
+
control: "6px"
|
|
55
|
+
pill: "9999px"
|
|
56
|
+
spacing:
|
|
57
|
+
panel: "20px"
|
|
58
|
+
section: "20px"
|
|
59
|
+
page: "24px"
|
|
60
|
+
rail: "56px"
|
|
61
|
+
components:
|
|
62
|
+
panel:
|
|
63
|
+
backgroundColor: "{colors.card}"
|
|
64
|
+
textColor: "{colors.foreground}"
|
|
65
|
+
rounded: "{rounded.panel}"
|
|
66
|
+
padding: "20px"
|
|
67
|
+
panel-title:
|
|
68
|
+
textColor: "{colors.foreground}"
|
|
69
|
+
typography: "{typography.panel-title}"
|
|
70
|
+
empty-state:
|
|
71
|
+
backgroundColor: "transparent"
|
|
72
|
+
textColor: "{colors.muted-foreground}"
|
|
73
|
+
rounded: "{rounded.row}"
|
|
74
|
+
padding: "40px 24px"
|
|
75
|
+
nav-link-selected:
|
|
76
|
+
backgroundColor: "{colors.selected}"
|
|
77
|
+
textColor: "{colors.foreground}"
|
|
78
|
+
rounded: "{rounded.row}"
|
|
79
|
+
padding: "8px 10px"
|
|
80
|
+
nav-link:
|
|
81
|
+
backgroundColor: "transparent"
|
|
82
|
+
textColor: "{colors.muted-foreground}"
|
|
83
|
+
rounded: "{rounded.row}"
|
|
84
|
+
padding: "8px 10px"
|
|
85
|
+
theme-toggle:
|
|
86
|
+
backgroundColor: "transparent"
|
|
87
|
+
textColor: "{colors.muted-foreground}"
|
|
88
|
+
rounded: "{rounded.control}"
|
|
89
|
+
size: "36px"
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
# Design System: Rigscope
|
|
93
|
+
|
|
94
|
+
## Overview
|
|
95
|
+
|
|
96
|
+
**Creative North Star: "The Rig-as-Console"**
|
|
97
|
+
|
|
98
|
+
A calm, modern monitoring console inspired by KDE's system monitor: clear resource
|
|
99
|
+
readouts, useful density, restrained surfaces, and charts that make changes easy to see.
|
|
100
|
+
The same visual language should support a single GPU rig and a fleet of servers.
|
|
101
|
+
|
|
102
|
+
This document provides direction and starting values. The frontmatter records the current
|
|
103
|
+
shared tokens; it does not freeze the palette, type scale, layout, or component inventory.
|
|
104
|
+
Existing CSS is the source for shipped values. Extend shared tokens coherently when a
|
|
105
|
+
new view needs them and update this record when those choices become reusable.
|
|
106
|
+
|
|
107
|
+
Prioritize accurate data, legibility, accessibility, and understandable interaction.
|
|
108
|
+
Specific styling choices below can evolve through normal implementation judgment; a
|
|
109
|
+
useful table, larger heading, additional surface, or new component needs no special approval.
|
|
110
|
+
|
|
111
|
+
**Key Characteristics:**
|
|
112
|
+
- Clear hierarchy and scan-friendly data, with room for both dense and spacious views.
|
|
113
|
+
- Quiet neutral surfaces, purposeful color, and recognizable metric/state meanings.
|
|
114
|
+
- Dark and light themes treated as full peers.
|
|
115
|
+
- Consistent components where tasks repeat; specialized presentation where tasks differ.
|
|
116
|
+
- Honest loading, empty, stale, unavailable, error, and disconnected states.
|
|
117
|
+
|
|
118
|
+
## Colors
|
|
119
|
+
|
|
120
|
+
Begin with the current neutral palette and blue accent. Reuse semantic tokens for common
|
|
121
|
+
roles so both themes stay coherent. The palette can expand to support new interactions,
|
|
122
|
+
alerts, chart series, hierarchy, and accessible contrast.
|
|
123
|
+
|
|
124
|
+
- **Primary:** accent for important actions, selection, focus, and useful emphasis. Filled
|
|
125
|
+
buttons, selected surfaces, and small brand treatments are allowed when they clarify hierarchy.
|
|
126
|
+
- **Neutral:** background/card/card-strong and foreground/muted-foreground are the starting
|
|
127
|
+
vocabulary. Add stronger dividers, intermediate text, or additional surfaces when needed;
|
|
128
|
+
there is no limit of two text colors or one border strength.
|
|
129
|
+
- **State:** healthy, warning, critical, informational, unknown and offline states should be
|
|
130
|
+
recognizable through labels/icons as well as color. Distinguish unavailable from healthy.
|
|
131
|
+
- **Metrics:** CPU blue, memory green, and swap amber are current defaults. Keep mappings
|
|
132
|
+
predictable within and across related views; add distinguishable GPU/resource series and
|
|
133
|
+
legends. A deliberate accessible palette update can revise defaults consistently.
|
|
134
|
+
|
|
135
|
+
Choose colors against their actual background in both themes. A token name alone does
|
|
136
|
+
not guarantee contrast. New reusable roles belong in the theme rather than scattered
|
|
137
|
+
component literals; exploratory values can be promoted once the design settles.
|
|
138
|
+
|
|
139
|
+
## Typography
|
|
140
|
+
|
|
141
|
+
System sans is the starting family for familiar, quick-loading UI. The existing page
|
|
142
|
+
heading (18px), panel heading/body (14px), supporting text (12px), and gauge value (20px)
|
|
143
|
+
are examples from the scaffold, not a required scale or a maximum size.
|
|
144
|
+
|
|
145
|
+
Use whatever hierarchy makes the task clear. Fleet summaries may need larger readouts;
|
|
146
|
+
dense tables may need compact labels; setup and error explanations need comfortable prose.
|
|
147
|
+
Use meaningful heading order, adequate line height, and wrapping that survives narrow
|
|
148
|
+
viewports and zoom. Do not shrink essential information to preserve a layout.
|
|
149
|
+
|
|
150
|
+
Use tabular numerals for aligned/changing measurements. Monospace is appropriate for
|
|
151
|
+
commands, addresses, identifiers, or logs when it improves reading. Include units and
|
|
152
|
+
consistent precision; stable text/column placement matters more than a particular class.
|
|
153
|
+
|
|
154
|
+
## Layout
|
|
155
|
+
|
|
156
|
+
Design for the information and the user's task. The current sidebar, header, and scrolling
|
|
157
|
+
main region are a useful baseline. Navigation, sidebar width, scrolling behavior, and
|
|
158
|
+
breakpoints may evolve as fleet, machine, settings and investigation views become real.
|
|
159
|
+
|
|
160
|
+
All pages render inside one shared content container owned by `AppShell`: centered,
|
|
161
|
+
capped at 1500px, with the standard page padding — page code adds no extra max-width or
|
|
162
|
+
centering wrappers. Workspace pages (Processes) fill the same container's full height.
|
|
163
|
+
Card grids that may hold a single item use auto-fit tracks so one card spans the row
|
|
164
|
+
instead of stranding beside empty columns.
|
|
165
|
+
The scaffold uses 20px panel gaps/padding and 24px page padding. Treat these as comfortable
|
|
166
|
+
defaults. Add compact/comfortable density, smaller mobile gutters, wider investigation
|
|
167
|
+
layouts, or other spacing when appropriate. Reuse shared spacing choices once established.
|
|
168
|
+
|
|
169
|
+
Tables, lists, charts, grouped sections, toolbars, and split views are valid building blocks.
|
|
170
|
+
A fleet table does not need a ring-gauge card for every machine, and every region does not
|
|
171
|
+
need a bordered panel. Use grouping and alignment before adding containers. Keep reading
|
|
172
|
+
order, reachable controls and critical status clear across screen sizes. Horizontal
|
|
173
|
+
scrolling can be appropriate for a dense table; contain it within that surface.
|
|
174
|
+
|
|
175
|
+
## Elevation & Depth
|
|
176
|
+
|
|
177
|
+
Prefer the existing quiet surfaces and subtle borders as the default. Tonal differences,
|
|
178
|
+
stronger dividers, subtle shadows, or a combination can establish hierarchy. Menus, dialogs,
|
|
179
|
+
popovers, and other overlays may need elevation to remain distinct from the data behind them.
|
|
180
|
+
|
|
181
|
+
There is no global ban on shadows, gradients, or additional layers. Use them selectively,
|
|
182
|
+
keep both themes readable, and avoid overwhelming chart marks or making ordinary data
|
|
183
|
+
panels appear interactive. Focus indicators can use the most visible accessible treatment.
|
|
184
|
+
|
|
185
|
+
## Shapes
|
|
186
|
+
|
|
187
|
+
The current 12px panel, 8px row, and 6px control radii provide a coherent starting family.
|
|
188
|
+
They are defaults, not mandatory dimensions. Tables can have square edges; compact tools,
|
|
189
|
+
chips, overlays, and new containers can choose shapes suited to their job.
|
|
190
|
+
|
|
191
|
+
Use circles for meaningful gauges/status marks where useful. Rings are an available
|
|
192
|
+
visualization, not a required signature for every metric. Choose charts and marks based
|
|
193
|
+
on what people need to compare.
|
|
194
|
+
|
|
195
|
+
## Components
|
|
196
|
+
|
|
197
|
+
### Existing foundations
|
|
198
|
+
|
|
199
|
+
`Panel`, `EmptyState`, `AppShell`, navigation, and theme toggle are reusable starting points.
|
|
200
|
+
Reuse them when they fit. Add variants or new components when that produces a clearer
|
|
201
|
+
interface; avoid forcing every view through `Panel` and `EmptyState`.
|
|
202
|
+
|
|
203
|
+
Current component dimensions and styles are examples of the shipped scaffold. A new
|
|
204
|
+
component should share the broader visual language and interaction conventions without
|
|
205
|
+
copying every measurement.
|
|
206
|
+
|
|
207
|
+
### Data and connection states
|
|
208
|
+
|
|
209
|
+
Separate first load, empty results, unsupported metrics, permission failure, stale samples,
|
|
210
|
+
collector disconnect, and hub disconnect. Keep last-known values visible when useful,
|
|
211
|
+
with an explicit timestamp/state. A missing metric must not look like successful zero usage.
|
|
212
|
+
|
|
213
|
+
Dashed placeholder rings belong to the current development scaffold. Future empty/loading
|
|
214
|
+
states can use contextual explanations, skeletons, compact inline states, and appropriate
|
|
215
|
+
next actions. Avoid presenting an unavailable control as a working action.
|
|
216
|
+
|
|
217
|
+
### Interactions and motion
|
|
218
|
+
|
|
219
|
+
Give controls understandable labels and relevant hover, focus, selected, disabled, loading,
|
|
220
|
+
and error feedback. Preserve keyboard access and accessible names when labels collapse.
|
|
221
|
+
Use familiar controls for filters, time ranges, enrollment, settings and confirmations.
|
|
222
|
+
|
|
223
|
+
Brief transitions can clarify changes and make the interface feel responsive. Existing
|
|
224
|
+
color transitions are a baseline; expansion, movement and other feedback are allowed when
|
|
225
|
+
useful. Honor reduced-motion preferences and keep frequent metric updates stable enough
|
|
226
|
+
for reading and selection.
|
|
227
|
+
|
|
228
|
+
Process tables fill the available workspace and preserve column proportions during live
|
|
229
|
+
updates and browser resizing. Minimum readable widths trigger scrolling inside the table;
|
|
230
|
+
the toolbar stays visible and table headers remain pinned while rows scroll. Drag column dividers to resize, use arrow keys on a focused
|
|
231
|
+
divider, or double-click to reset. View mode, per-table sorting and widths persist in the
|
|
232
|
+
browser; search, expanded applications, pause and machine selection last for the tab session.
|
|
233
|
+
Machine selection is shared across Fleet, Overview, History and Processes for the tab.
|
|
234
|
+
The sidebar keeps Fleet as the parent of a single machine selector and indented
|
|
235
|
+
Overview/History/Processes links. Global hub pages follow in a separate group. Header
|
|
236
|
+
breadcrumbs show Fleet / machine / view; page-level tabs and pickers are omitted. Fleet
|
|
237
|
+
rows show compact CPU/memory trends received since sign-in. Overview combines CPU/GPU
|
|
238
|
+
and RAM/VRAM into two charts in one fixed ten-minute panel. History owns range and metric
|
|
239
|
+
selection for detailed investigation. Its picker groups CPU, memory, GPU, storage and
|
|
240
|
+
network controls, keeping core/card selection inside the relevant group. Global Select all / Unselect all share the Metrics disclosure row;
|
|
241
|
+
per-resource All / None actions update metric selection in one operation, respecting
|
|
242
|
+
machine capabilities and the hub's recorded metric catalog. Automatic history polling
|
|
243
|
+
leaves Refresh visually unchanged; manual refresh alone disables and animates it until
|
|
244
|
+
the request settles. Resource
|
|
245
|
+
sections fill the content width; related charts share a row on desktop and stack on
|
|
246
|
+
phones. CPU usage, I/O wait and CPU pressure share a percentage chart, while temperature
|
|
247
|
+
and power retain separate units. RAM and filesystem capacity each use one chart with
|
|
248
|
+
a Bytes / % switch when both stored metrics are selected; unit choices persist per
|
|
249
|
+
machine and visible exports follow the displayed unit. Swap belongs in the Memory
|
|
250
|
+
section. Recent usage legends number GPU cards to distinguish identical models. Collector diagnostics remain behind a bounded disclosure;
|
|
251
|
+
obvious explanatory copy is omitted, including on sign-in.
|
|
252
|
+
|
|
253
|
+
Live sampling, process updates and visible-tab history refreshes default to one second.
|
|
254
|
+
Refresh requests never overlap or replace existing charts with loading panels. Process
|
|
255
|
+
freshness changes update the status indicator without adding a banner or moving the table.
|
|
256
|
+
|
|
257
|
+
Per-core History defaults to all available cores, with an explicit All cores / None
|
|
258
|
+
and a scrollable checkbox picker for custom subsets. Up to eight series use lines;
|
|
259
|
+
larger selections use a scrollable heatmap of stored bucket peaks, with latest/peak
|
|
260
|
+
values and optional busiest-first order. Missing readings remain unfilled; recorded
|
|
261
|
+
gaps mask the heatmap. Requests allow the collector contract's 1024 cores while
|
|
262
|
+
retaining the existing scan/time budgets and partial-result indicators.
|
|
263
|
+
|
|
264
|
+
History retains its time range and per-machine metric, GPU-card and series visibility
|
|
265
|
+
choices in the browser; its machine, control expansion and auto-refresh state last for the tab.
|
|
266
|
+
Returning to Processes keeps the last snapshot visible while fresh data is requested.
|
|
267
|
+
Snapshots stay in memory, are scoped to the browser login, and show their freshness state.
|
|
268
|
+
|
|
269
|
+
## Do's and Don'ts
|
|
270
|
+
|
|
271
|
+
### Do:
|
|
272
|
+
- **Do** choose the layout and density that help people answer the monitoring question.
|
|
273
|
+
- **Do** reuse or extend shared tokens/components when the behavior or role repeats.
|
|
274
|
+
- **Do** preserve units, freshness, explicit states, and consistent metric meanings.
|
|
275
|
+
- **Do** verify keyboard behavior, zoom, contrast, and both themes when changing UI.
|
|
276
|
+
- **Do** evolve this guidance when a better reusable pattern emerges.
|
|
277
|
+
|
|
278
|
+
### Don't:
|
|
279
|
+
- **Don't** treat scaffold dimensions or examples as permanent product requirements.
|
|
280
|
+
- **Don't** force every screen into the same cards, chart types, or scrolling structure.
|
|
281
|
+
- **Don't** rely on color alone for status, selection, or chart interpretation.
|
|
282
|
+
- **Don't** show stale/unavailable data as healthy live measurements or fake interactivity.
|
|
283
|
+
- **Don't** sacrifice legibility or access to controls to preserve a visual convention.
|
|
284
|
+
|
|
285
|
+
## Release setup
|
|
286
|
+
|
|
287
|
+
Rigscope retains the established console styling. Fleet and Connections expose an
|
|
288
|
+
admin-only Add machine action that links to the collector enrollment section. Generated
|
|
289
|
+
commands use the current hub origin, and prompt privately for the separate, one-time
|
|
290
|
+
grant. Copy controls have visible status and a manual-selection fallback. Enrollment
|
|
291
|
+
adds no live-state banners above monitoring data.
|
|
292
|
+
|
|
293
|
+
## Product and identity
|
|
294
|
+
|
|
295
|
+
Rigscope is a self-hosted Linux resource/process monitor for a machine owner or small-fleet operator. Each collector connects outbound to independently operated hubs; each hub owns its users, permissions and history. The main tasks are spotting stale/unhealthy machines, inspecting resource history and opening live process detail. Remote mutating process actions are outside this release.
|
|
296
|
+
|
|
297
|
+
App surfaces use Operate mode: precise data, quiet surfaces, stable live updates and familiar controls. Freshness changes update existing status indicators without inserting banners above data. Interface copy consists of labels, values and actionable errors; omit redundant explanatory paragraphs.
|
|
298
|
+
|
|
299
|
+
The identity is an open rack frame around a rising trace and two sample points. `BrandMark` is the shared, decorative 24-unit SVG in the sidebar and sign-in row; the neighboring Rigscope text/link provides its accessible name. The app icon uses the same geometry with a dark backing and bright blue stroke for light/dark browser chrome. It is legible at 16–32px, with no animation, raster assets or layout changes. Keep this small brand gesture separate from metric semantics.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Triet (@Triet1402)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|