@naisys/hub 3.0.0-beta.34 → 3.0.0-beta.36
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/README.md +60 -0
- package/dist/naisysHub.js +27 -6
- package/npm-shrinkwrap.json +26 -26
- package/package.json +6 -6
package/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# NAISYS Hub
|
|
2
|
+
|
|
3
|
+
[← Back to main README](../../README.md)
|
|
4
|
+
|
|
5
|
+
The hub is the central server and source of truth for a NAISYS cluster. Runners and supervisors connect over WebSocket + REST; the hub owns persistence (mail, context logs, cost, variables) so runners are ephemeral and can be restarted or moved between machines without losing state.
|
|
6
|
+
|
|
7
|
+
## Running
|
|
8
|
+
|
|
9
|
+
Most installations run the hub in-process with the supervisor UI and ERP — see the [main README](../../README.md). To run the hub alone:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @naisys/hub
|
|
13
|
+
npx naisys-hub
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Hosts then connect with `npx naisys --hub=https://<server>/hub`. If the hub isn't already public, expose it with a reverse proxy or [ngrok](https://ngrok.com/).
|
|
17
|
+
|
|
18
|
+
> **Note:** Remote auto-update from the supervisor UI only works when the hub runs attached to a `naisys` runner (the integrated stack). Running `naisys-hub` solo skips the runner that performs the update.
|
|
19
|
+
|
|
20
|
+
## Configuration
|
|
21
|
+
|
|
22
|
+
Standalone hub reads configuration from `.env`:
|
|
23
|
+
|
|
24
|
+
- `NAISYS_FOLDER` - persistent data folder for the hub database, logs, and access key
|
|
25
|
+
- `SERVER_PORT` - HTTP port; defaults to `3300`
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
### Core
|
|
30
|
+
|
|
31
|
+
- WebSocket + REST server with `hub-protocol` shared types between hub and clients
|
|
32
|
+
- Heartbeat service for online runners/supervisors and agent status
|
|
33
|
+
- Run-session tracking with keep-alive and authoritative online/offline state
|
|
34
|
+
- Per-app host filter (naisys-host vs supervisor-host)
|
|
35
|
+
|
|
36
|
+
### Persistence ([doc 001](../../docs/001-database-design.md))
|
|
37
|
+
|
|
38
|
+
The hub owns mail, context logs and [attachments](../../docs/011-mail-attachments.md), cost history, and variables, so runners stay ephemeral and replaceable.
|
|
39
|
+
|
|
40
|
+
### Multi-machine ([doc 005](../../docs/005-multi-machine-redux.md))
|
|
41
|
+
|
|
42
|
+
- Hub is the single source of truth; runners are ephemeral
|
|
43
|
+
- Duplicate host-connection prevention — a new connection supersedes a dead one
|
|
44
|
+
|
|
45
|
+
### Security ([doc 010](../../docs/010-hub-security.md))
|
|
46
|
+
|
|
47
|
+
- `Authorization: Bearer` header auth with a rotatable access key
|
|
48
|
+
- Hardened spawning: no shell interpretation, timeouts on `execFileSync`
|
|
49
|
+
- API keys read from headers, not query params
|
|
50
|
+
- Hub socket served at `/hub` for reverse-proxy friendliness (TLS terminated at the proxy)
|
|
51
|
+
|
|
52
|
+
### Deployment
|
|
53
|
+
|
|
54
|
+
- Reverse-proxy-friendly path strategy (`<app>/api/...`) and unified port strategy ([doc 009](../../docs/009-port-strategy.md))
|
|
55
|
+
- npm bin entry points: `naisys`, `naisys-hub`, `naisys-supervisor`, `naisys-erp`
|
|
56
|
+
- Ngrok-friendly (skip-browser-warning header)
|
|
57
|
+
|
|
58
|
+
## License
|
|
59
|
+
|
|
60
|
+
MIT
|
package/dist/naisysHub.js
CHANGED
|
@@ -44,16 +44,15 @@ export const startHub = async (startupType, startSupervisor, plugins, startupAge
|
|
|
44
44
|
// Create host registrar for tracking NAISYS instance connections
|
|
45
45
|
const hostRegistrar = await createHostRegistrar(hubDatabaseService);
|
|
46
46
|
// Create Fastify instance (TLS is handled by the reverse proxy)
|
|
47
|
-
const fastify = Fastify();
|
|
47
|
+
const fastify = Fastify({ pluginTimeout: 60_000 });
|
|
48
48
|
// Register HTTP attachment upload/download routes
|
|
49
49
|
createHubAttachmentService(fastify, hubDatabaseService, logService);
|
|
50
|
-
// Attach Socket.IO to the underlying HTTP server
|
|
50
|
+
// Attach Socket.IO to the underlying HTTP server.
|
|
51
|
+
// No CORS config: only Node socket.io-clients (NAISYS instance, supervisor server)
|
|
52
|
+
// connect here, and they aren't subject to CORS. Omitting the header keeps
|
|
53
|
+
// browsers from initiating handshakes.
|
|
51
54
|
const io = new Server(fastify.server, {
|
|
52
55
|
path: "/hub/socket.io",
|
|
53
|
-
cors: {
|
|
54
|
-
origin: "*", // In production, restrict this
|
|
55
|
-
methods: ["GET", "POST"],
|
|
56
|
-
},
|
|
57
56
|
});
|
|
58
57
|
const naisysServer = createNaisysServer(io, hubAccessKey, logService, hostRegistrar);
|
|
59
58
|
// Register hub access key rotation handler
|
|
@@ -105,6 +104,28 @@ export const startHub = async (startupType, startSupervisor, plugins, startupAge
|
|
|
105
104
|
if (startupType === "hosted") {
|
|
106
105
|
logService.disableConsole();
|
|
107
106
|
}
|
|
107
|
+
// Hosted mode: parent process owns signal handling
|
|
108
|
+
if (startupType === "standalone") {
|
|
109
|
+
let shuttingDown = false;
|
|
110
|
+
const handleShutdown = async (signal) => {
|
|
111
|
+
if (shuttingDown) {
|
|
112
|
+
console.log("[Hub] Force exit");
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
shuttingDown = true;
|
|
116
|
+
logService.log(`[Hub] Shutting down (${signal})...`);
|
|
117
|
+
try {
|
|
118
|
+
await io.close();
|
|
119
|
+
await fastify.close();
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
console.error("[Hub] Error during shutdown:", err);
|
|
123
|
+
}
|
|
124
|
+
process.exit(0);
|
|
125
|
+
};
|
|
126
|
+
process.on("SIGTERM", () => void handleShutdown("SIGTERM"));
|
|
127
|
+
process.on("SIGINT", () => void handleShutdown("SIGINT"));
|
|
128
|
+
}
|
|
108
129
|
return { serverPort };
|
|
109
130
|
}
|
|
110
131
|
catch (err) {
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naisys/hub",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.36",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@naisys/hub",
|
|
9
|
-
"version": "3.0.0-beta.
|
|
9
|
+
"version": "3.0.0-beta.36",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@naisys/common": "3.0.0-beta.
|
|
12
|
-
"@naisys/common-node": "3.0.0-beta.
|
|
13
|
-
"@naisys/hub-database": "3.0.0-beta.
|
|
14
|
-
"@naisys/hub-protocol": "3.0.0-beta.
|
|
11
|
+
"@naisys/common": "3.0.0-beta.36",
|
|
12
|
+
"@naisys/common-node": "3.0.0-beta.36",
|
|
13
|
+
"@naisys/hub-database": "3.0.0-beta.36",
|
|
14
|
+
"@naisys/hub-protocol": "3.0.0-beta.36",
|
|
15
15
|
"commander": "^14.0.3",
|
|
16
16
|
"dotenv": "^17.3.1",
|
|
17
17
|
"fastify": "^5.8.2",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"node": ">=22.0.0"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"@naisys/supervisor": "3.0.0-beta.
|
|
27
|
+
"@naisys/supervisor": "3.0.0-beta.36"
|
|
28
28
|
},
|
|
29
29
|
"peerDependenciesMeta": {
|
|
30
30
|
"@naisys/supervisor": {
|
|
@@ -189,32 +189,32 @@
|
|
|
189
189
|
"license": "MIT"
|
|
190
190
|
},
|
|
191
191
|
"node_modules/@naisys/common": {
|
|
192
|
-
"version": "3.0.0-beta.
|
|
193
|
-
"resolved": "https://registry.npmjs.org/@naisys/common/-/common-3.0.0-beta.
|
|
194
|
-
"integrity": "sha512-
|
|
192
|
+
"version": "3.0.0-beta.36",
|
|
193
|
+
"resolved": "https://registry.npmjs.org/@naisys/common/-/common-3.0.0-beta.36.tgz",
|
|
194
|
+
"integrity": "sha512-a5EYqKvnL1Uy1pdslLZVMQERbo3ZtnMvhKa5B4GQJ/ziwM5zgMfbUFUEDniJRnta4dtIU5GxgzxBxmin+gMbhw==",
|
|
195
195
|
"dependencies": {
|
|
196
196
|
"semver": "^7.7.4",
|
|
197
197
|
"zod": "^4.3.6"
|
|
198
198
|
}
|
|
199
199
|
},
|
|
200
200
|
"node_modules/@naisys/common-node": {
|
|
201
|
-
"version": "3.0.0-beta.
|
|
202
|
-
"resolved": "https://registry.npmjs.org/@naisys/common-node/-/common-node-3.0.0-beta.
|
|
203
|
-
"integrity": "sha512-
|
|
201
|
+
"version": "3.0.0-beta.36",
|
|
202
|
+
"resolved": "https://registry.npmjs.org/@naisys/common-node/-/common-node-3.0.0-beta.36.tgz",
|
|
203
|
+
"integrity": "sha512-pgzHJuh6OH6wiNU4PRV8sSNaBqWCYateD7+tWHnwvDwVOzwce8ttLNtsK+NQzwQqp+vjPAMpfJ9yMqoOttXgbA==",
|
|
204
204
|
"dependencies": {
|
|
205
|
-
"@naisys/common": "3.0.0-beta.
|
|
205
|
+
"@naisys/common": "3.0.0-beta.36",
|
|
206
206
|
"better-sqlite3": "^12.6.2",
|
|
207
207
|
"js-yaml": "^4.1.1",
|
|
208
208
|
"pino": "^10.3.1"
|
|
209
209
|
}
|
|
210
210
|
},
|
|
211
211
|
"node_modules/@naisys/hub-database": {
|
|
212
|
-
"version": "3.0.0-beta.
|
|
213
|
-
"resolved": "https://registry.npmjs.org/@naisys/hub-database/-/hub-database-3.0.0-beta.
|
|
214
|
-
"integrity": "sha512-
|
|
212
|
+
"version": "3.0.0-beta.36",
|
|
213
|
+
"resolved": "https://registry.npmjs.org/@naisys/hub-database/-/hub-database-3.0.0-beta.36.tgz",
|
|
214
|
+
"integrity": "sha512-FiJJCaOARun5jbTwX2VwXgEy5xDqlMi7X1ZSpxSn0jMv3dzniupCYYAYyO4muwXdFLNO2vMnhUdmhK/m2k7ouw==",
|
|
215
215
|
"dependencies": {
|
|
216
|
-
"@naisys/common": "3.0.0-beta.
|
|
217
|
-
"@naisys/common-node": "3.0.0-beta.
|
|
216
|
+
"@naisys/common": "3.0.0-beta.36",
|
|
217
|
+
"@naisys/common-node": "3.0.0-beta.36",
|
|
218
218
|
"@prisma/adapter-better-sqlite3": "^7.5.0",
|
|
219
219
|
"@prisma/client": "^7.5.0",
|
|
220
220
|
"better-sqlite3": "^12.6.2",
|
|
@@ -222,11 +222,11 @@
|
|
|
222
222
|
}
|
|
223
223
|
},
|
|
224
224
|
"node_modules/@naisys/hub-protocol": {
|
|
225
|
-
"version": "3.0.0-beta.
|
|
226
|
-
"resolved": "https://registry.npmjs.org/@naisys/hub-protocol/-/hub-protocol-3.0.0-beta.
|
|
227
|
-
"integrity": "sha512-
|
|
225
|
+
"version": "3.0.0-beta.36",
|
|
226
|
+
"resolved": "https://registry.npmjs.org/@naisys/hub-protocol/-/hub-protocol-3.0.0-beta.36.tgz",
|
|
227
|
+
"integrity": "sha512-JCxS982SjYUws3vg3O5XgoeoC0Pllhm7qLdqXTJpZY9v+SA5VGvu5/xvOURspNuIbpRayQkUx7cakTmQUQFKrw==",
|
|
228
228
|
"dependencies": {
|
|
229
|
-
"@naisys/common": "3.0.0-beta.
|
|
229
|
+
"@naisys/common": "3.0.0-beta.36",
|
|
230
230
|
"zod": "^4.3.6"
|
|
231
231
|
}
|
|
232
232
|
},
|
|
@@ -640,9 +640,9 @@
|
|
|
640
640
|
}
|
|
641
641
|
},
|
|
642
642
|
"node_modules/ajv": {
|
|
643
|
-
"version": "8.
|
|
644
|
-
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.
|
|
645
|
-
"integrity": "sha512-
|
|
643
|
+
"version": "8.20.0",
|
|
644
|
+
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
|
|
645
|
+
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
|
|
646
646
|
"license": "MIT",
|
|
647
647
|
"dependencies": {
|
|
648
648
|
"fast-deep-equal": "^3.1.3",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naisys/hub",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.36",
|
|
4
4
|
"description": "NAISYS Hub - Adds persistence and multi-instance coordination to NAISYS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/naisysHub.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"!dist/**/*.d.ts.map"
|
|
32
32
|
],
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@naisys/supervisor": "3.0.0-beta.
|
|
34
|
+
"@naisys/supervisor": "3.0.0-beta.36"
|
|
35
35
|
},
|
|
36
36
|
"peerDependenciesMeta": {
|
|
37
37
|
"@naisys/supervisor": {
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@naisys/common": "3.0.0-beta.
|
|
43
|
-
"@naisys/common-node": "3.0.0-beta.
|
|
44
|
-
"@naisys/hub-database": "3.0.0-beta.
|
|
45
|
-
"@naisys/hub-protocol": "3.0.0-beta.
|
|
42
|
+
"@naisys/common": "3.0.0-beta.36",
|
|
43
|
+
"@naisys/common-node": "3.0.0-beta.36",
|
|
44
|
+
"@naisys/hub-database": "3.0.0-beta.36",
|
|
45
|
+
"@naisys/hub-protocol": "3.0.0-beta.36",
|
|
46
46
|
"commander": "^14.0.3",
|
|
47
47
|
"dotenv": "^17.3.1",
|
|
48
48
|
"fastify": "^5.8.2",
|