remote-dsh 0.6.0 → 0.7.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.
Files changed (3) hide show
  1. package/README.md +3 -2
  2. package/dist/bin.js +39 -17
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -4,10 +4,11 @@ Secure remote access for [DeepSeek Harness](https://github.com/deepseek-ai/deeps
4
4
 
5
5
  ```bash
6
6
  npm install -g remote-dsh
7
- rdsh serve # LAN auth gateway in front of dsh web (M1 MVP)
7
+ rdsh host setup lan # write ~/.rdsh/host.json (LAN gateway: pair auth)
8
+ rdsh host serve # run the gateway in the foreground
8
9
  ```
9
10
 
10
- > **v0.1.0** is a name-reservation skeleton. Commands land with the M1 MVP.
11
+ > See `doc/overview/usage.md` for the full manual (`rdsh host setup lan|cloud`, `rdsh host join <hub>`, `rdsh hub serve`, ...).
11
12
 
12
13
  ## License
13
14
 
package/dist/bin.js CHANGED
@@ -10,7 +10,6 @@
10
10
  */
11
11
  import { createInterface } from "node:readline";
12
12
  import { rm } from "node:fs/promises";
13
- import { hostname as osHostname } from "node:os";
14
13
  import { dirname } from "node:path";
15
14
  import { serve, join, registerJoin, findDsh, selfRevoke, readPersistedToken, clearPersistedToken, UserManager, resolveConfigPath, loadConfig, saveConfig, installService, uninstallService, serviceStatus, HOST_SERVICE_NAME, JOIN_SERVICE_NAME, HUB_SERVICE_NAME, } from "rdsh-gateway";
16
15
  import { loadHubConfig, resolveHubConfigPath, HubDb, hashPassword, serveHub, } from "rdsh-hub";
@@ -25,7 +24,7 @@ Usage:
25
24
  rdsh host leave Unregister this machine from the hub
26
25
  rdsh host user ... Manage gateway users (LAN/cloud password auth)
27
26
  rdsh hub serve Start the hub server (cloud, multi-host)
28
- rdsh hub user add|passwd|rm|ls|unlock|reset-2fa
27
+ rdsh hub user add|passwd|rm|ls|unlock|reset-2fa|ban|unban
29
28
  rdsh hub audit ls Audit log (login/2FA/sharing/email events)
30
29
  rdsh hub host ls|revoke List / revoke hosts (revoke drops the tunnel instantly)
31
30
  rdsh hub service ... Run hub as a systemd/launchd service
@@ -61,7 +60,7 @@ Run the hub server or manage it.
61
60
 
62
61
  Subcommands:
63
62
  serve Start the hub server (TLS required)
64
- user add|passwd|rm|ls|unlock|reset-2fa Manage users (admin creates accounts; unlock / reset-2fa)
63
+ user add|passwd|rm|ls|unlock|reset-2fa|ban|unban Manage users (admin creates accounts; unlock / reset-2fa / ban / unban)
65
64
  audit ls [--user <n>] [--event <e>] [--since 24h|7d] Query the audit log
66
65
  host ls|revoke List / revoke hosts (revoke drops the tunnel instantly)
67
66
  service install|status|uninstall Run hub as a systemd/launchd service
@@ -286,7 +285,7 @@ async function handleHostJoin(args, configPath) {
286
285
  const config = await loadConfig(target);
287
286
  config.mode = "join";
288
287
  config.hub = hubUrl;
289
- config.name = opts.name ?? osHostname();
288
+ config.name = outcome.name;
290
289
  config.insecure = outcome.insecure;
291
290
  config.dshPath = opts.dshPath ?? findDsh() ?? config.dshPath;
292
291
  await saveConfig(target, config);
@@ -358,7 +357,7 @@ async function maybeRegisterForServiceInstall(args, target) {
358
357
  const cfg = await loadConfig(target);
359
358
  cfg.mode = "join";
360
359
  cfg.hub = maybeHub;
361
- cfg.name = joinOpts.name ?? osHostname();
360
+ cfg.name = outcome.name;
362
361
  cfg.insecure = outcome.insecure;
363
362
  cfg.dshPath = joinOpts.dshPath ?? findDsh() ?? cfg.dshPath;
364
363
  await saveConfig(target, cfg);
@@ -584,20 +583,21 @@ async function handleHubUser(args, configPath) {
584
583
  case "add": {
585
584
  const name = args[1];
586
585
  if (name === undefined)
587
- throw new Error("usage: rdsh hub user add <name> [--no-password]");
586
+ throw new Error("usage: rdsh hub user add <name> [--no-password] [--role <user|readonly|operator|admin>]");
588
587
  const noPassword = args.includes("--no-password");
588
+ const roleIdx = args.indexOf("--role");
589
+ const role = roleIdx >= 0 && args[roleIdx + 1] !== undefined ? args[roleIdx + 1] : "user";
590
+ if (!["user", "readonly", "operator", "admin"].includes(role))
591
+ throw new Error(`invalid role '${role}' (user|readonly|operator|admin)`);
589
592
  const hubConfigPath = resolveHubConfigPath(configPath);
590
593
  if (db.getUserByName(name) !== null)
591
594
  throw new Error(`user '${name}' already exists`);
592
- if (noPassword) {
593
- db.createUser(name, "scrypt:disabled", new Date().toISOString(), true);
594
- console.log(`rdsh: user '${name}' created they must set a password on first sign-in (${hubConfigPath})`);
595
- }
596
- else {
597
- const password = await promptPasswordTwice(`password for ${name}: `);
598
- db.createUser(name, await hashPassword(password));
599
- console.log(`rdsh: user '${name}' created (hub db: ${db.path})`);
600
- }
595
+ const user = noPassword
596
+ ? db.createUser(name, "scrypt:disabled", new Date().toISOString(), true)
597
+ : db.createUser(name, await hashPassword(await promptPasswordTwice(`password for ${name}: `)));
598
+ if (role !== "user")
599
+ db.setRole(user.id, role);
600
+ console.log(`rdsh: user '${name}' created (role: ${role}${noPassword ? " — must set password on first sign-in" : ""})`);
601
601
  return;
602
602
  }
603
603
  case "passwd": {
@@ -614,7 +614,7 @@ async function handleHubUser(args, configPath) {
614
614
  }
615
615
  case "ls": {
616
616
  const users = db.listUsers();
617
- console.log(users.length > 0 ? users.map((u) => u.name).join("\n") : "(no users)");
617
+ console.log(users.length > 0 ? users.map((u) => `${u.name}\t${u.role}`).join("\n") : "(no users)");
618
618
  return;
619
619
  }
620
620
  case "rm": {
@@ -651,8 +651,30 @@ async function handleHubUser(args, configPath) {
651
651
  console.log(`rdsh: 2FA reset for '${name}' (their sessions revoked)`);
652
652
  return;
653
653
  }
654
+ case "ban": {
655
+ const name = args[1];
656
+ if (name === undefined)
657
+ throw new Error("usage: rdsh hub user ban <name>");
658
+ const user = db.getUserByName(name);
659
+ if (user === null)
660
+ throw new Error(`user '${name}' not found`);
661
+ db.setAccountStatus(user.id, "banned");
662
+ console.log(`rdsh: user '${name}' banned (login + host access blocked)`);
663
+ return;
664
+ }
665
+ case "unban": {
666
+ const name = args[1];
667
+ if (name === undefined)
668
+ throw new Error("usage: rdsh hub user unban <name>");
669
+ const user = db.getUserByName(name);
670
+ if (user === null)
671
+ throw new Error(`user '${name}' not found`);
672
+ db.setAccountStatus(user.id, "active");
673
+ console.log(`rdsh: user '${name}' unbanned (plan restored)`);
674
+ return;
675
+ }
654
676
  default:
655
- throw new Error("usage: rdsh hub user add|passwd|ls|rm|unlock|reset-2fa");
677
+ throw new Error("usage: rdsh hub user add|passwd|ls|rm|unlock|reset-2fa|ban|unban");
656
678
  }
657
679
  }
658
680
  finally {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remote-dsh",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Secure remote access for DeepSeek Harness: rdsh serve / rdsh join / rdsh hub",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,8 +23,8 @@
23
23
  "node": ">=22"
24
24
  },
25
25
  "dependencies": {
26
- "rdsh-gateway": "0.4.0",
27
- "rdsh-hub": "0.4.0"
26
+ "rdsh-gateway": "0.5.0",
27
+ "rdsh-hub": "0.5.0"
28
28
  },
29
29
  "scripts": {
30
30
  "build": "tsc -p tsconfig.json",