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
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
# Production operations
|
|
2
|
+
|
|
3
|
+
This guide covers the supported single-host, two-process deployment:
|
|
4
|
+
|
|
5
|
+
- `dist/hub.cjs` — Node 26 custom server: listener, WebSocket collectors,
|
|
6
|
+
browser SSE, authentication and the production Next.js handler from `.next`.
|
|
7
|
+
- `dist/collector.cjs` — outbound-only collector with durable per-destination
|
|
8
|
+
outboxes.
|
|
9
|
+
- `dist/ops.cjs` — inspect, migrate, backup, restore, package, install,
|
|
10
|
+
activate, rollback and bounded synthetic measurement.
|
|
11
|
+
|
|
12
|
+
There is no Next.js standalone output and no `next start`. The hub runs the
|
|
13
|
+
custom server from the installed release directory; the production UI must be
|
|
14
|
+
present in `.next`.
|
|
15
|
+
|
|
16
|
+
All paths below are examples. Choose a prefix and state directory owned by the
|
|
17
|
+
service user. Paths containing spaces are supported by the generated units.
|
|
18
|
+
|
|
19
|
+
## Managed CLI operations
|
|
20
|
+
|
|
21
|
+
For a per-user installation created by `rigscope install` (default state
|
|
22
|
+
`~/.local/state/rigscope`), the CLI owns the runtime, component units and release pairing:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
rigscope status
|
|
26
|
+
rigscope doctor [--json]
|
|
27
|
+
rigscope upgrade [--from PACKAGE] [--timeout SECONDS]
|
|
28
|
+
rigscope rollback [--backup PATH] [--timeout SECONDS]
|
|
29
|
+
rigscope recover-password [--user owner] [--password-file PATH] [--enable]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`doctor` is read-only. It checks Node, private configuration and state
|
|
33
|
+
permissions, the installed and previous runtimes, the component units, the database
|
|
34
|
+
and schema, free space, hub port/Unix-socket state, role-appropriate listener
|
|
35
|
+
health, configured destinations with TLS certificate validation, and procfs or
|
|
36
|
+
RAPL readability for a collector. A hub without a collector is valid, and a
|
|
37
|
+
collector without a local hub database is valid. Output contains counts and
|
|
38
|
+
paths, never password hashes, collector tokens or environment values.
|
|
39
|
+
|
|
40
|
+
`upgrade` stages the package without touching the active runtime, stops the
|
|
41
|
+
running components, takes a consistent pre-upgrade hub database backup when one
|
|
42
|
+
exists, and activates the new runtime. It restarts only components that were
|
|
43
|
+
running before the upgrade and verifies them within `--timeout` seconds (default
|
|
44
|
+
25). Verification follows the installation's enabled components:
|
|
45
|
+
|
|
46
|
+
- the active package reports the staged version;
|
|
47
|
+
- restarted component services are active;
|
|
48
|
+
- a restarted hub answers `status: "ok"` with the expected version;
|
|
49
|
+
- an existing hub database passes integrity and ledger checks and reaches the
|
|
50
|
+
staged runtime's supported schema;
|
|
51
|
+
- a restarted collector produces a fresh sampling health marker.
|
|
52
|
+
|
|
53
|
+
A failed start, migration or health wait restores the previous runtime and the
|
|
54
|
+
paired pre-upgrade database when the old runtime cannot read the new schema. The
|
|
55
|
+
replaced database is preserved first; credentials, collector identities and
|
|
56
|
+
outboxes are not rewritten. `release-state.json` in the state directory records
|
|
57
|
+
which runtime each backup belongs to. An inactive installation is staged and
|
|
58
|
+
activated without starting; live health is then reported as skipped.
|
|
59
|
+
|
|
60
|
+
`rollback` swaps to `runtime-previous` and validates it with the same bounded
|
|
61
|
+
health and database checks. If the current schema is compatible it keeps the
|
|
62
|
+
database unchanged, including post-upgrade data. If the previous runtime cannot
|
|
63
|
+
read it, rollback restores the paired pre-upgrade backup, refuses when no
|
|
64
|
+
compatible backup is recorded, and prints where the replaced newer database was
|
|
65
|
+
preserved. For installations created before release state existed, pass an
|
|
66
|
+
explicit compatible copy with `--backup PATH`. Rollback never silently deletes
|
|
67
|
+
the newer database and never runs old code against a newer schema.
|
|
68
|
+
|
|
69
|
+
`recover-password` is offline recovery for the durable managed user store. It
|
|
70
|
+
requires the hub service to be stopped, takes the hub database lease and
|
|
71
|
+
refuses a live or ambiguous lock. Enter the password at the private prompt, or
|
|
72
|
+
pass a private `0600` file with `--password-file`. It updates only that managed
|
|
73
|
+
user's hash in the database, clears `disabled` only with `--enable`, writes a
|
|
74
|
+
bounded `user.password-recovery` audit row and bumps a durable session-epoch
|
|
75
|
+
marker. It never edits `config.json` or `HUB_BROWSER_USERS`, so bootstrap
|
|
76
|
+
password changes do not overwrite managed users. Restarting the hub invalidates
|
|
77
|
+
all in-memory browser sessions; sign in again with the new password.
|
|
78
|
+
|
|
79
|
+
## Low-level manifest archive workflow
|
|
80
|
+
|
|
81
|
+
The remaining archive deployment examples assume a source checkout with built
|
|
82
|
+
artifacts. They use a manifest `.tar.gz`, which is different from the npm `.tgz`
|
|
83
|
+
used by `rigscope install` and `rigscope upgrade`. For ordinary installations,
|
|
84
|
+
follow [installation](installation.md) and the managed commands above. The npm
|
|
85
|
+
package excludes source helper scripts and does not require users to build it.
|
|
86
|
+
|
|
87
|
+
### Build and package
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
npm ci
|
|
91
|
+
npm run build:ui # production .next
|
|
92
|
+
npm run build:runtime # dist/hub.cjs, dist/collector.cjs, dist/ops.cjs
|
|
93
|
+
node scripts/package-release.cjs --output /var/tmp/rigscope-release.tar.gz
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The archive contains the built runtime, `.next` without its cache, package and
|
|
97
|
+
lock files, the repository's `next.config.js`, `tsconfig.json`,
|
|
98
|
+
operational docs and the `packaging/` examples. It deliberately excludes source, tests, git data,
|
|
99
|
+
`node_modules`, private environment files, SQLite databases, keys and logs.
|
|
100
|
+
`manifest.json` lists every packaged file with size and SHA-256; the installer
|
|
101
|
+
re-verifies it before activation.
|
|
102
|
+
|
|
103
|
+
Production dependencies are installed inside each staged release:
|
|
104
|
+
|
|
105
|
+
```sh
|
|
106
|
+
cd /home/operator/.local/opt/rigscope/releases/<version>
|
|
107
|
+
npm ci --omit=dev
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`install --install-deps` can run that command explicitly, but the installer
|
|
111
|
+
never runs npm implicitly for activation. If a package mirror is unavailable,
|
|
112
|
+
stage without activation and install from an approved mirror; do not weaken npm
|
|
113
|
+
security policy just to make installation pass. Isolated tests use a synthetic
|
|
114
|
+
dependency tree and do not perform remote installs.
|
|
115
|
+
|
|
116
|
+
## Stage and activate
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
node scripts/install-release.cjs \
|
|
120
|
+
--source /var/tmp/rigscope-release.tar.gz \
|
|
121
|
+
--prefix /home/operator/.local/opt/rigscope \
|
|
122
|
+
--state-dir /home/operator/.local/state/rigscope \
|
|
123
|
+
--units-dir /home/operator/.config/systemd/user
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The installer creates:
|
|
127
|
+
|
|
128
|
+
```text
|
|
129
|
+
<prefix>/
|
|
130
|
+
releases/<version>/ immutable built release + manifest
|
|
131
|
+
releases/<version>/node_modules/
|
|
132
|
+
current -> releases/<version>
|
|
133
|
+
previous -> releases/<previous> (retained for rollback)
|
|
134
|
+
<state>/
|
|
135
|
+
hub/telemetry.sqlite hub database (0700 dir, 0600 file)
|
|
136
|
+
hub.env private EnvironmentFile (0600, no secrets printed)
|
|
137
|
+
collector.env private EnvironmentFile (0600)
|
|
138
|
+
collector/collector.json collector identity/enrollment (created by collector)
|
|
139
|
+
outbox/<sha256(url)[0:16]>/ per-destination collector outboxes
|
|
140
|
+
backups/ private pre-upgrade/pre-activation database copies
|
|
141
|
+
install-state.json versions, schema backups, no credentials
|
|
142
|
+
run/ private runtime directory for a Unix socket
|
|
143
|
+
<units-dir>/
|
|
144
|
+
rigscope-hub.service
|
|
145
|
+
rigscope-collector.service
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Staging does not switch `current` or start anything. After production
|
|
149
|
+
dependencies are installed and the old hub is stopped, activate explicitly:
|
|
150
|
+
|
|
151
|
+
```sh
|
|
152
|
+
node scripts/install-release.cjs activate \
|
|
153
|
+
--prefix /home/operator/.local/opt/rigscope \
|
|
154
|
+
--state-dir /home/operator/.local/state/rigscope \
|
|
155
|
+
--version <version> --confirm-stopped
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Activation order is fixed:
|
|
159
|
+
|
|
160
|
+
1. Validate the release manifest, hashes and production dependencies.
|
|
161
|
+
2. Verify no hub lock exists and the operator confirmed the hub is stopped.
|
|
162
|
+
3. Inspect the current database schema.
|
|
163
|
+
4. If migration is needed: write a consistent online backup, then migrate, then
|
|
164
|
+
verify integrity and the target schema. A failed migration restores the
|
|
165
|
+
pre-migration backup and leaves `current` unchanged.
|
|
166
|
+
5. Atomically switch `current`, retaining `previous` and a schema-backup record.
|
|
167
|
+
6. Print (never execute) systemd commands.
|
|
168
|
+
|
|
169
|
+
If validation or migration fails, a good database is never silently replaced.
|
|
170
|
+
The pre-migration backup path is printed. First installation with no database
|
|
171
|
+
creates and migrates a new private database.
|
|
172
|
+
|
|
173
|
+
## systemd user units
|
|
174
|
+
|
|
175
|
+
The generated units use an absolute Node 26 executable, absolute paths,
|
|
176
|
+
`WorkingDirectory=<prefix>/current`, a private `EnvironmentFile`, journald
|
|
177
|
+
logging, `Restart=on-failure`, `NoNewPrivileges=yes`, `PrivateTmp=yes`,
|
|
178
|
+
`UMask=0077`, `ProtectSystem=strict`, and explicit writable state/database/cache paths.
|
|
179
|
+
|
|
180
|
+
Startup is explicit and is not performed by the installer:
|
|
181
|
+
|
|
182
|
+
```sh
|
|
183
|
+
systemctl --user daemon-reload
|
|
184
|
+
systemctl --user enable --now rigscope-hub.service rigscope-collector.service
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Automatic startup after logout/host reboot requires an explicit administrator
|
|
188
|
+
choice to enable user lingering for that account:
|
|
189
|
+
|
|
190
|
+
```sh
|
|
191
|
+
sudo loginctl enable-linger operator
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Review the generated units and private env files first. Health and observation:
|
|
195
|
+
|
|
196
|
+
```sh
|
|
197
|
+
curl --fail --silent http://127.0.0.1:8081/api/health
|
|
198
|
+
systemctl --user status rigscope-hub.service rigscope-collector.service
|
|
199
|
+
journalctl --user -u rigscope-hub.service -f
|
|
200
|
+
journalctl --user -u rigscope-collector.service -f
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Shutdown is bounded: the hub targets five seconds and the collector three
|
|
204
|
+
seconds; the generated `TimeoutStopSec` leaves a ten- and seven-second slack
|
|
205
|
+
respectively. Keep those times at or above the process deadlines.
|
|
206
|
+
|
|
207
|
+
## Configuration
|
|
208
|
+
|
|
209
|
+
`RIGSCOPE_OPS_DEBUG` enables operation diagnostics; keep diagnostic output private. `RIGSCOPE_HUB_LOCK_FILE` overrides the hub lease path when needed; use the same path for the hub and operations commands.
|
|
210
|
+
|
|
211
|
+
The generated `hub.env` and `collector.env` contain only comments. Empty
|
|
212
|
+
configuration fails closed: no `HUB_BROWSER_USERS` means browser data is
|
|
213
|
+
unavailable, and no collector credentials/destinations means no fleet data.
|
|
214
|
+
Never copy the public demo credentials from the examples to a real host.
|
|
215
|
+
|
|
216
|
+
Loopback development:
|
|
217
|
+
|
|
218
|
+
```sh
|
|
219
|
+
HUB_HOST=127.0.0.1
|
|
220
|
+
HUB_PORT=8081
|
|
221
|
+
HUB_DATABASE_PATH=/home/operator/.local/state/rigscope/hub/telemetry.sqlite
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Browser users and collectors belong in the private environment file. Generate
|
|
225
|
+
browser password hashes locally with `scripts/hash-browser-password.cjs`; never
|
|
226
|
+
store plaintext passwords or hashes in shared logs.
|
|
227
|
+
|
|
228
|
+
Remote mode uses a private Unix socket behind an external TLS terminator:
|
|
229
|
+
|
|
230
|
+
```sh
|
|
231
|
+
HUB_PUBLIC_ORIGIN=https://monitor.example.invalid
|
|
232
|
+
HUB_SOCKET_PATH=/home/operator/.local/state/rigscope/run/hub.sock
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
The parent directory must be private and owned by the service user. The
|
|
236
|
+
installer's state `run/` directory is already writable by the unit. Remote
|
|
237
|
+
health checks go through the socket with the exact Host:
|
|
238
|
+
|
|
239
|
+
```sh
|
|
240
|
+
curl --fail --silent --unix-socket <socket> \
|
|
241
|
+
-H 'Host: monitor.example.invalid' http://localhost/api/health
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
This example hostname and every `demo-token-*` value are public fixtures, not a
|
|
245
|
+
deployment. See `development.md` for the exact origin/Host/cookie
|
|
246
|
+
boundary. Never expose the loopback HTTP listener remotely without the private
|
|
247
|
+
socket/TLS boundary and authentication.
|
|
248
|
+
|
|
249
|
+
Collector enrollment remains separate from browser sessions:
|
|
250
|
+
|
|
251
|
+
```sh
|
|
252
|
+
COLLECTOR_ENROLL_URL=ws://127.0.0.1:8081/api/collector/connect
|
|
253
|
+
COLLECTOR_ENROLL_TOKEN=<one-use grant>
|
|
254
|
+
COLLECTOR_MODE=real
|
|
255
|
+
COLLECTOR_STATE_FILE=/home/operator/.local/state/rigscope/collector/collector.json
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Remove the one-use grant after enrollment and start or restart the collector. The
|
|
259
|
+
hub does not need a restart. Enrollment state
|
|
260
|
+
and outboxes live outside the repository.
|
|
261
|
+
|
|
262
|
+
For an isolated local check without touching the real deployment, the public demo
|
|
263
|
+
grant from the packaging examples can drive a loopback enrollment and collection
|
|
264
|
+
run. These are deliberate demo strings only, never a real deployment:
|
|
265
|
+
|
|
266
|
+
```sh
|
|
267
|
+
HUB_STATE_FILE="$PWD/.rigscope-local/hub/enrollment.json" \
|
|
268
|
+
HUB_ENROLLMENT_GRANTS="$(node -e 'console.log(JSON.stringify([{token:"demo-token-enrollment-local",expiresAt:new Date(Date.now()+300000).toISOString()}]))')" \
|
|
269
|
+
npm start
|
|
270
|
+
|
|
271
|
+
# In another terminal:
|
|
272
|
+
COLLECTOR_STATE_FILE="$PWD/.rigscope-local/collector/state.json" \
|
|
273
|
+
COLLECTOR_ENROLL_URL='ws://127.0.0.1:8081/api/collector/connect' \
|
|
274
|
+
COLLECTOR_ENROLL_TOKEN='demo-token-enrollment-local' \
|
|
275
|
+
npm run collector:enroll
|
|
276
|
+
|
|
277
|
+
# Start real local collection with the saved credential:
|
|
278
|
+
COLLECTOR_STATE_FILE="$PWD/.rigscope-local/collector/state.json" npm run collector:start
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Enrollment posts `{collectorId}` to `/api/collector/enroll`; the bearer grant travels
|
|
282
|
+
only in the Authorization header. Grants must expire within fifteen minutes and are
|
|
283
|
+
consumed across restarts. Plaintext is allowed only for literal loopback addresses;
|
|
284
|
+
WSS enrollment uses HTTPS with ordinary certificate validation.
|
|
285
|
+
|
|
286
|
+
## Database commands
|
|
287
|
+
|
|
288
|
+
All commands take explicit paths. They print no credentials, user hashes,
|
|
289
|
+
webhook URLs, tokens or record payloads.
|
|
290
|
+
|
|
291
|
+
```sh
|
|
292
|
+
# Read-only schema/integrity/size/table summary.
|
|
293
|
+
node dist/ops.cjs inspect --database /path/telemetry.sqlite
|
|
294
|
+
|
|
295
|
+
# Consistent single-file online backup. Does NOT migrate the source.
|
|
296
|
+
node dist/ops.cjs backup \
|
|
297
|
+
--database /path/telemetry.sqlite \
|
|
298
|
+
--output /path/private-backups/telemetry-$(date +%Y%m%dT%H%M%S).sqlite
|
|
299
|
+
|
|
300
|
+
# Offline guarded migration. Existing databases require --confirm-stopped.
|
|
301
|
+
node dist/ops.cjs migrate \
|
|
302
|
+
--database /path/telemetry.sqlite \
|
|
303
|
+
--backup-dir /path/private-backups --confirm-stopped
|
|
304
|
+
|
|
305
|
+
# Guarded restore over an existing database: both flags are required.
|
|
306
|
+
node dist/ops.cjs restore \
|
|
307
|
+
--input /path/private-backups/telemetry-....sqlite \
|
|
308
|
+
--database /path/telemetry.sqlite \
|
|
309
|
+
--replace --confirm-stopped
|
|
310
|
+
|
|
311
|
+
# Offline managed-user recovery; password comes from a private 0600 file.
|
|
312
|
+
node dist/ops.cjs recover-admin \
|
|
313
|
+
--database /path/telemetry.sqlite \
|
|
314
|
+
--user owner --password-file /path/private-recovery-password --enable
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Safety rules enforced by `backup`/`restore`:
|
|
318
|
+
|
|
319
|
+
- The hub database is one SQLite file. The online backup copies all tables in
|
|
320
|
+
that file: telemetry, history rollups, receipts/gaps, machine latest and
|
|
321
|
+
inventory, the collector registry/grants/audit, admin users/audit, and alert
|
|
322
|
+
rules/incidents/jobs/webhook state. There is no partial table selection.
|
|
323
|
+
- Backup opens the source read-only, runs `integrity_check`, stages the copy,
|
|
324
|
+
converts it to a self-contained DELETE-journal file, verifies the staged copy,
|
|
325
|
+
sets mode 0600 and atomically renames it. The source schema is never migrated.
|
|
326
|
+
- Restore validates the input integrity and migration ledger, refuses a schema
|
|
327
|
+
newer than this operations build, refuses to overwrite the target without
|
|
328
|
+
`--replace --confirm-stopped`, and refuses if a hub lock is present.
|
|
329
|
+
- It stages and verifies a copy first. For an existing target it checkpoints the
|
|
330
|
+
old database, takes a pre-restore backup, then removes only the old WAL/SHM
|
|
331
|
+
sidecars after proof that the hub is stopped, and atomically replaces the
|
|
332
|
+
main file. A failed validation never overwrites the target.
|
|
333
|
+
- The hub process lease is `<databasePath>.hub.lock` (JSON `{pid,instance}`).
|
|
334
|
+
Operations refuses while it exists, even if the PID looks stale, because only
|
|
335
|
+
the hub's own startup proof may recover a proven-dead lease. The hub removes
|
|
336
|
+
it on clean shutdown/exit; operators must inspect a lock and never delete it
|
|
337
|
+
blindly.
|
|
338
|
+
- Restoring an older-schema backup is allowed; the matching release migrates it
|
|
339
|
+
on the next hub start. Never start an old release against a newer schema.
|
|
340
|
+
|
|
341
|
+
Schema versions are derived from the build's migration ledger. The current
|
|
342
|
+
ledger includes telemetry, latest-session identity, admin, alerts and collector
|
|
343
|
+
registry migrations. A newer database must be opened by newer code; an old
|
|
344
|
+
release must never be pointed at a newer schema. `inspect` reports this state.
|
|
345
|
+
|
|
346
|
+
## Consistent backup set
|
|
347
|
+
|
|
348
|
+
The database backup is not the whole installation. A restorable set is:
|
|
349
|
+
|
|
350
|
+
1. Hub SQLite database: `telemetry.sqlite` (includes registry/admin/alerts).
|
|
351
|
+
Use `ops backup`; do not copy the main file alone while the hub is running.
|
|
352
|
+
2. Enrollment/config state when configured: `HUB_STATE_FILE` (for
|
|
353
|
+
example `hub/enrollment.json`, the import source for previously enrolled
|
|
354
|
+
collectors) and the private hub environment file. These
|
|
355
|
+
contain credentials: protect and copy them only between private locations.
|
|
356
|
+
3. Collector identity/enrollment: `collector/collector.json`.
|
|
357
|
+
4. Collector outboxes: `outbox/<destination-hash>/outbox.sqlite` per hub URL,
|
|
358
|
+
which may contain unacknowledged telemetry. Replay is at-least-once; the hub
|
|
359
|
+
deduplicates by collector/run/sequence.
|
|
360
|
+
5. Optional operational metadata: `install-state.json`, units and the built
|
|
361
|
+
release. Keep the release matching the database schema for rollback.
|
|
362
|
+
|
|
363
|
+
For a consistent set, prefer stopping both services cleanly, then run the online
|
|
364
|
+
database backup and copy the other private files. For an online backup, the SQLite
|
|
365
|
+
copy is internally consistent, but JSON identity/outbox files should be copied in
|
|
366
|
+
a quiescent moment; outbox copies may lag and replay duplicates are harmless.
|
|
367
|
+
|
|
368
|
+
Restore the database with `ops restore`; copy non-database state back separately
|
|
369
|
+
with the same ownership and modes. Never silently copy another installation's private keys, browser credentials or unrelated files.
|
|
370
|
+
|
|
371
|
+
## Upgrade and rollback
|
|
372
|
+
|
|
373
|
+
For an upgrade:
|
|
374
|
+
|
|
375
|
+
1. Package and stage the new release; install `npm ci --omit=dev` there.
|
|
376
|
+
2. Stop the old hub/collector and verify the lock is gone.
|
|
377
|
+
3. Run `install ... --activate --confirm-stopped` (or `activate`).
|
|
378
|
+
4. The installer backs up, migrates and verifies before switching `current`.
|
|
379
|
+
5. Start/enable services explicitly and check health. If the services were
|
|
380
|
+
already installed:
|
|
381
|
+
`systemctl --user restart rigscope-hub.service rigscope-collector.service`.
|
|
382
|
+
|
|
383
|
+
Rollback:
|
|
384
|
+
|
|
385
|
+
```sh
|
|
386
|
+
node dist/ops.cjs rollback \
|
|
387
|
+
--prefix /home/operator/.local/opt/rigscope \
|
|
388
|
+
--state-dir /home/operator/.local/state/rigscope \
|
|
389
|
+
--confirm-stopped
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Rollback is refused while the hub lock exists. If the database schema is newer
|
|
393
|
+
than the previous release's manifest, rollback restores the recorded matching
|
|
394
|
+
pre-upgrade backup (verified against that release's schema) before switching
|
|
395
|
+
`current`. If no matching backup exists, it refuses rather than claiming an old
|
|
396
|
+
binary can read a newer schema. The replaced database is itself backed up first.
|
|
397
|
+
|
|
398
|
+
### Upgrade ordering
|
|
399
|
+
|
|
400
|
+
Within a user installation or this manifest archive layout, hub and collector
|
|
401
|
+
share one release: upgrade the installation together. Stop the hub and
|
|
402
|
+
collector, activate the new release (which migrates and verifies the database),
|
|
403
|
+
then start both services from the same release. Avoid running an old collector
|
|
404
|
+
against a newer hub or vice versa for longer than the restart itself. Do not roll
|
|
405
|
+
a hub back below the schema its database already uses; `rollback` enforces that
|
|
406
|
+
boundary, and collector rollback keeps its private state and outboxes. Process
|
|
407
|
+
detail remains request-scoped and is never persisted or included in the backup
|
|
408
|
+
set. Separate machines and hubs are upgraded independently. System installations
|
|
409
|
+
use the component controls described in [installation](installation.md#system-component-lifecycle).
|
|
410
|
+
|
|
411
|
+
On upgrade from the previous collector endpoint, saved `/api/collector/v1/connect`
|
|
412
|
+
URLs normalize to `/api/collector/connect` without changing identity, credentials,
|
|
413
|
+
sharing policy or pending enrollment recovery proofs. The collector recovers the
|
|
414
|
+
old URL's outbox before connecting. If both queue directories exist, it imports
|
|
415
|
+
missing record identities in a transaction before removing the old directory.
|
|
416
|
+
Stored metrics and gaps with the previous `protocolVersion: 2` envelope are
|
|
417
|
+
decoded into the current wire format at the outbox boundary; record identities
|
|
418
|
+
and previously offered gap payloads are preserved. Wire parsers remain strict.
|
|
419
|
+
|
|
420
|
+
## Measurement
|
|
421
|
+
|
|
422
|
+
`ops measure` is a bounded synthetic runner, not a capacity guarantee:
|
|
423
|
+
|
|
424
|
+
```sh
|
|
425
|
+
node dist/ops.cjs measure --machines 2 --batches 30 --records-per-batch 5 \
|
|
426
|
+
--gpus 2 --viewers 2 --json
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
It writes synthetic records through the real `TelemetryStore` into a
|
|
430
|
+
temporary private database and reports accepted/rejected/busy counts, ingestion
|
|
431
|
+
latency, event-loop delay/utilization, RSS, database/WAL size, store queue and
|
|
432
|
+
flush counters, and one history-query latency. The output is labelled synthetic.
|
|
433
|
+
Defaults are intentionally small; upper bounds are 1,000 machines, 2,000 batches,
|
|
434
|
+
32 records per batch and 100,000 records total. It never opens a service socket
|
|
435
|
+
or contacts a hub. `--keep` retains the temporary directory for inspection. The
|
|
436
|
+
library accepts `historyConcurrency` for overlapping History request rounds;
|
|
437
|
+
the CLI exposes it as `--history-concurrency N` (default 1).
|
|
438
|
+
|
|
439
|
+
Current integration notes: storage commits batches of at most 32 records and the
|
|
440
|
+
history query has a 25,000-row/100 ms budget; a 512-record synthetic benchmark
|
|
441
|
+
showed roughly 407 ms transactions. Measure on the actual deployment before
|
|
442
|
+
choosing cadence, retention or viewer counts. No latency or capacity guarantee
|
|
443
|
+
is implied by these development numbers.
|
|
444
|
+
|
|
445
|
+
For sustained concurrent viewers, collector reconnects/replay, slow SSE
|
|
446
|
+
consumers and a fleet beyond 50 machines, use the isolated harness described in
|
|
447
|
+
[scale-validation.md](scale-validation.md). It spawns a temporary loopback hub
|
|
448
|
+
and never contacts the live service.
|
|
449
|
+
|
|
450
|
+
## Verification limits
|
|
451
|
+
|
|
452
|
+
Default repository tests exercise backup/restore, newer-schema refusal, corrupted input,
|
|
453
|
+
lock refusal, installer staging/activation/rollback and failed-upgrade recovery
|
|
454
|
+
in isolated temporary directories. CLI fixture tests additionally cover doctor
|
|
455
|
+
redaction and role separation, inactive and live upgrade validation, paired
|
|
456
|
+
rollback restore/refusal, compatible rollback without data replacement, and
|
|
457
|
+
offline password recovery with lock refusal and audit. They do not start
|
|
458
|
+
services, enable units, touch Tailscale, use real credentials, modify developer
|
|
459
|
+
state, or perform npm network installs; fixture dependency trees stand in for
|
|
460
|
+
production `npm ci`.
|
|
461
|
+
Production visual/render verification and integrated runtime tests are separate.
|
|
462
|
+
The opt-in real-service checks in [releasing](releasing.md#verify-the-exact-archive)
|
|
463
|
+
do install disposable systemd user services and production npm dependencies;
|
|
464
|
+
they remove their test units afterward and use separate state and launchers.
|
|
465
|
+
|
|
466
|
+
Pass `--node /absolute/path/to/node` only when the unit must use a Node 26
|
|
467
|
+
executable different from the one running the installer. The path must be an
|
|
468
|
+
absolute regular file; use the release's `node_modules` installed with
|
|
469
|
+
`npm ci --omit=dev`, never a development-only tree.
|
|
470
|
+
|
|
471
|
+
## Storage budgets and pressure recovery
|
|
472
|
+
|
|
473
|
+
Each Collector Hub connection owns policy filtering, cadence, inventory and its
|
|
474
|
+
durable outbox submission. On restart, recovered metrics are sanitized with the
|
|
475
|
+
current sharing policy before the connection starts; capture-time cadence is not
|
|
476
|
+
reapplied to retained records. Endpoint upgrade recovery and aggregate budgets
|
|
477
|
+
continue to use the existing outboxes. Hub startup restores stored telemetry,
|
|
478
|
+
cadence, inventory and metadata through Sample ingestion while retaining a
|
|
479
|
+
disconnected state until an authenticated Collector reconnects.
|
|
480
|
+
|
|
481
|
+
The default hub main-file plus WAL budget is 2 GiB, shared by every SQLite table.
|
|
482
|
+
The main file has a page-count limit; WAL reserves up to 128 MiB inside that budget.
|
|
483
|
+
Telemetry writes return busy on pressure or SQLITE_FULL, with no receipt/ack for a
|
|
484
|
+
failed transaction. Retention reclaims old raw/one-minute points in bounded chunks
|
|
485
|
+
while preserving the newest hour; hourly rollups retain their configured age window.
|
|
486
|
+
A full newest-hour working set must fit the deployment's budget. Outboxes retry
|
|
487
|
+
while the operator frees space or provisions a larger supported configuration.
|
|
488
|
+
|
|
489
|
+
Collector defaults are 64 MiB logical JSON and 80 MiB physical main+WAL per hub,
|
|
490
|
+
256 MiB logical and 640 MiB physical across eight destinations. Physical pressure
|
|
491
|
+
evicts only pending metrics, records dropped intervals, and protects in-flight
|
|
492
|
+
records. Failed gap writes are held in bounded memory and retried after recovery;
|
|
493
|
+
an abrupt power loss can still lose that in-memory notice.
|
|
494
|
+
|
|
495
|
+
New databases use incremental page reclamation. Existing databases created without
|
|
496
|
+
auto-vacuum may keep allocated pages after retention deletes rows. Startup reports
|
|
497
|
+
pressure and limits growth; it never runs an unbounded VACUUM. Back up the database,
|
|
498
|
+
stop the hub and inspect file/WAL sizes before offline maintenance. These are
|
|
499
|
+
application/SQLite budgets rather than an operating-system filesystem quota. An
|
|
500
|
+
atomic transaction can briefly increase WAL before its post-commit checkpoint;
|
|
501
|
+
blocked checkpoints leave pressure visible and prevent continued ingestion. Keep
|
|
502
|
+
free disk space for backups, SQLite sidecars and release artifacts.
|
|
503
|
+
|
|
504
|
+
Collector state and enrollment file locks now contain an owner PID and instance.
|
|
505
|
+
A proven-dead owner is recovered with inode checks. Legacy empty `.lock` files have
|
|
506
|
+
no owner proof and intentionally require one manual inspection: verify no collector
|
|
507
|
+
or enrollment writer is running before removing that specific abandoned file.
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
Generated user units omit `ProtectKernelModules=yes`: on the target user manager,
|
|
511
|
+
that directive fails before Node starts with `218/CAPABILITIES`. Normal user
|
|
512
|
+
privileges and `NoNewPrivileges=yes` already prevent gaining module-loading
|
|
513
|
+
privileges. PrivateTmp, ProtectSystem=strict, explicit writable paths and the other
|
|
514
|
+
validated user-unit hardening remain enabled. Do not copy root-only hardening into
|
|
515
|
+
user units without starting and stopping an isolated unit on that host.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Releasing Rigscope
|
|
2
|
+
|
|
3
|
+
The first public version is `0.1.0`. Source and issue links target
|
|
4
|
+
`https://github.com/Triet1402/rigscope`. Create that repository and push the
|
|
5
|
+
release source before npm publication. The package includes MIT licensing,
|
|
6
|
+
dependency notices, the security policy and [release notes](../CHANGELOG.md).
|
|
7
|
+
|
|
8
|
+
## Recommended release order
|
|
9
|
+
|
|
10
|
+
1. Finish the version, public docs, release notes and repository metadata. Commit
|
|
11
|
+
those changes. Keep the installation examples in the package ready for the
|
|
12
|
+
version being published.
|
|
13
|
+
2. Push the source to GitHub and run the manual CI workflow on that revision.
|
|
14
|
+
This repository deliberately has no push, pull-request or scheduled CI
|
|
15
|
+
triggers. A local result is not a GitHub Actions result.
|
|
16
|
+
3. Build one npm archive from the final revision. Retain it, its SHA-256 checksum
|
|
17
|
+
and verification results. Test and publish that archive without rebuilding it.
|
|
18
|
+
4. Run the publish dry run, check the npm account, and publish the verified archive.
|
|
19
|
+
5. Verify the registry version and install it into a disposable test installation.
|
|
20
|
+
Check sign-in, fresh telemetry and the installed command.
|
|
21
|
+
6. Tag the exact source revision as `v0.1.0`, push the tag, and create a GitHub
|
|
22
|
+
Release with the release notes, verified archive and checksum. Announce it
|
|
23
|
+
after the registry installation works.
|
|
24
|
+
|
|
25
|
+
For subsequent releases, update the package and lockfile versions together
|
|
26
|
+
(for example, `npm version patch --no-git-tag-version`), update the release notes,
|
|
27
|
+
and repeat the same sequence. A published name/version cannot be overwritten,
|
|
28
|
+
so a correction after publication needs a new version. Prereleases should use
|
|
29
|
+
an explicit tag such as `next`; ordinary `rigscope upgrade` follows `latest`.
|
|
30
|
+
|
|
31
|
+
## Build the final archive
|
|
32
|
+
|
|
33
|
+
Run from the source checkout with Linux and Node.js 26+:
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
npm ci
|
|
37
|
+
npm run typecheck
|
|
38
|
+
mkdir -p out/release
|
|
39
|
+
npm pack --pack-destination out/release
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`npm pack` runs `prepack`, which regenerates dependency notices, builds fresh
|
|
43
|
+
runtime/UI artifacts and verifies them. If notice generation changes a tracked
|
|
44
|
+
file, include that change in the release commit before producing the final
|
|
45
|
+
archive. Reuse the archive for every check below. Replace `0.1.0` in these
|
|
46
|
+
commands when releasing another version.
|
|
47
|
+
|
|
48
|
+
## Verify the exact archive
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
node scripts/verify-package.cjs ./out/release/rigscope-0.1.0.tgz
|
|
52
|
+
npm run verify:installed -- --archive ./out/release/rigscope-0.1.0.tgz
|
|
53
|
+
npm test
|
|
54
|
+
node scripts/test-runtime.cjs
|
|
55
|
+
node scripts/test.cjs --suite development
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Package inspection verifies the built CLI/runtime/UI and excludes source tests,
|
|
59
|
+
Git data, private environment files and caches. Inspect the file list for
|
|
60
|
+
unexpected state, databases, credentials or logs. Installed-package verification
|
|
61
|
+
uses production dependencies in a temporary directory, audits the resolved
|
|
62
|
+
dependency tree and checks the CLI version plus authenticated sign-in/History.
|
|
63
|
+
|
|
64
|
+
The following opt-in checks require a working Linux systemd user manager. They
|
|
65
|
+
create disposable installations with separate state, launchers, ports and unit
|
|
66
|
+
names, then remove their services. They do not select an existing installation.
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
RIGSCOPE_TEST_ARCHIVE="$PWD/out/release/rigscope-0.1.0.tgz" \
|
|
70
|
+
node --import tsx --test tests/cli-install.integration.ts
|
|
71
|
+
node scripts/verify-operations.cjs ./out/release/rigscope-0.1.0.tgz
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
These cover installation, pairing, independent component controls, bootstrap
|
|
75
|
+
removal, retained-data reinstall, upgrade/rollback, failed-start recovery and
|
|
76
|
+
offline password recovery. Runtime tests additionally cover authenticated HTTPS,
|
|
77
|
+
SSE, collector connections, persistence and reconnect behavior in isolated setups.
|
|
78
|
+
|
|
79
|
+
On the reference host with 48 logical cores, two RTX 3090s and an ASPEED adapter,
|
|
80
|
+
run the hardware-specific test explicitly:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
RIGSCOPE_REAL_HW=1 node --import tsx --test tests/sampling-real.test.ts
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
That test reads the actual host and is skipped by default. Its exact inventory
|
|
87
|
+
assertions are specific to that rig; it is not a portable hardware test.
|
|
88
|
+
|
|
89
|
+
Record the final checksum after verification:
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
cd out/release
|
|
93
|
+
sha256sum rigscope-0.1.0.tgz > SHA256SUMS
|
|
94
|
+
sha256sum --check SHA256SUMS
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Keep the source revision, archive checksum, check results and any skips together.
|
|
98
|
+
Record boot enablement separately from an actual reboot. Physical laptop testing
|
|
99
|
+
and synthetic scale workloads are separate evidence; see
|
|
100
|
+
[hardware support](installation.md#hardware) and [scale validation](scale-validation.md).
|
|
101
|
+
|
|
102
|
+
## Publish dry run and publication
|
|
103
|
+
|
|
104
|
+
Run these commands from the source checkout. Sign in interactively if needed,
|
|
105
|
+
then verify the account and preview the exact archive:
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
npm login --registry=https://registry.npmjs.org
|
|
109
|
+
npm whoami --registry=https://registry.npmjs.org
|
|
110
|
+
npm publish ./out/release/rigscope-0.1.0.tgz --access public --tag latest \
|
|
111
|
+
--registry=https://registry.npmjs.org --dry-run
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The dry run does not publish, reserve the name, or prove that registry
|
|
115
|
+
authorization and two-factor authentication will succeed. The repository
|
|
116
|
+
metadata does not establish npm package ownership.
|
|
117
|
+
|
|
118
|
+
When releasing, this command actually publishes the verified archive publicly:
|
|
119
|
+
|
|
120
|
+
```sh
|
|
121
|
+
npm publish ./out/release/rigscope-0.1.0.tgz --access public --tag latest \
|
|
122
|
+
--registry=https://registry.npmjs.org
|
|
123
|
+
npm view rigscope@0.1.0 version dist.integrity --registry=https://registry.npmjs.org
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Then use `npx --yes rigscope@0.1.0 install` with a disposable `--state-dir`, an
|
|
127
|
+
unused `--port` and an isolated `XDG_BIN_HOME` for the registry installation
|
|
128
|
+
check. Uninstall that test installation afterward. Use the same isolation
|
|
129
|
+
settings for all test commands so the check does not select a real installation.
|
|
130
|
+
|
|
131
|
+
The public quick start uses `npx --yes rigscope@latest install --boot` and the
|
|
132
|
+
installed `rigscope upgrade`. Archive commands remain available before npm
|
|
133
|
+
publication and for explicit version selection. Users do not need a global npm
|
|
134
|
+
installation of Rigscope.
|
|
135
|
+
|
|
136
|
+
GitHub Actions trusted publishing can automate later releases. Configure it for
|
|
137
|
+
the actual repository and publishing workflow; the current CI workflow only
|
|
138
|
+
verifies and does not publish. See npm's
|
|
139
|
+
[publishing documentation](https://docs.npmjs.com/cli/commands/npm-publish/) and
|
|
140
|
+
[trusted publishing guide](https://docs.npmjs.com/trusted-publishers/).
|
|
141
|
+
|
|
142
|
+
## Alternative manifest archives
|
|
143
|
+
|
|
144
|
+
`npm run package:release` creates an operations `.tar.gz` with a hashed manifest.
|
|
145
|
+
It is a separate format from the npm `.tgz`. The low-level installer validates
|
|
146
|
+
size/hash and required artifacts before activation. Production dependencies must
|
|
147
|
+
be installed in the staged release; activation never silently runs npm or service
|
|
148
|
+
commands. See [operations](operations.md#low-level-manifest-archive-workflow) and
|
|
149
|
+
[system installation](installation.md#system-installation).
|
|
150
|
+
|
|
151
|
+
Configuration, database schema and wire-protocol revisions are internal
|
|
152
|
+
compatibility checks, independent of the application package version.
|