@lumi-ai-lab/harness-data 0.0.22 → 0.0.23

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 CHANGED
@@ -32,6 +32,14 @@ Update an existing runtime interactively:
32
32
  npx @lumi-ai-lab/harness-data update
33
33
  ```
34
34
 
35
+ Reconfigure CAS credentials after an account/password change or after `.qdm-auth` was deleted:
36
+
37
+ ```bash
38
+ npx @lumi-ai-lab/harness-data auth --dir /path/to/runtime
39
+ ```
40
+
41
+ The command recreates `.qdm-auth/cas`, stores the new encrypted CAS credentials, refreshes the CMR, Indicators, and SQL tokens, and validates all three tokens.
42
+
35
43
  Diagnose a runtime:
36
44
 
37
45
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumi-ai-lab/harness-data",
3
- "version": "0.0.22",
3
+ "version": "0.0.23",
4
4
  "description": "Installer and updater for Harness Data",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -2,8 +2,9 @@ import { installCommand } from "./commands/install.js";
2
2
  import { updateCommand } from "./commands/update.js";
3
3
  import { doctorCommand } from "./commands/doctor.js";
4
4
  import { versionCommand } from "./commands/version.js";
5
+ import { authCommand } from "./commands/auth.js";
5
6
 
6
- const commands = new Set(["install", "update", "doctor", "version"]);
7
+ const commands = new Set(["install", "update", "auth", "doctor", "version"]);
7
8
 
8
9
  function parse(argv) {
9
10
  const args = argv.slice(2);
@@ -31,17 +32,19 @@ export async function main(argv) {
31
32
  const { command, options, unknown } = parse(argv);
32
33
  if (command === "install") return installCommand(options);
33
34
  if (command === "update") return updateCommand(options);
35
+ if (command === "auth") return authCommand(options);
34
36
  if (command === "doctor") return doctorCommand(options);
35
37
  if (command === "version") return versionCommand(options);
36
- console.log(`Usage: harness-data <install|update|doctor|version> [options]
38
+ console.log(`Usage: harness-data <install|update|auth|doctor|version> [options]
37
39
 
38
40
  Commands:
39
41
  install Install a Harness Data runtime in the current directory
40
42
  update Interactively check and apply runtime, CLI, and wikis updates
43
+ auth Configure CAS credentials and refresh access tokens
41
44
  doctor Diagnose workspace CLI, config, auth, index, and Agent hooks
42
45
  version Print installer, repository, wikis, and manifest versions
43
46
 
44
- Install options:
47
+ Install and auth options:
45
48
  --dir PATH Runtime directory (default: current directory)
46
49
  --agent NAME claude, codex, pi, openclaw, hermes, both, or all
47
50
  --github-token TOKEN GitHub token for private Release assets
@@ -0,0 +1,34 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { findWorkspaceDir } from "../lib/paths.js";
4
+ import { packageVersion } from "../lib/package.js";
5
+ import { binaryName } from "../lib/platform.js";
6
+ import { blank, header, ok, step } from "../lib/log.js";
7
+ import { configureTokens, writeCasCredentials } from "./install.js";
8
+
9
+ const requiredBinaries = ["cas-cli", "qdm-cmr-cli", "qdm-indicators-cli", "qdm-sql-cli"];
10
+
11
+ function validateAuthRuntime(runtimeDir) {
12
+ if (!fs.existsSync(runtimeDir)) throw new Error(`runtime directory does not exist: ${runtimeDir}`);
13
+ for (const name of requiredBinaries) {
14
+ const file = path.join(runtimeDir, "bin", binaryName(name));
15
+ if (!fs.existsSync(file)) throw new Error(`runtime CLI is missing: ${file}`);
16
+ }
17
+ }
18
+
19
+ export async function authCommand(options = {}) {
20
+ const runtimeDir = findWorkspaceDir(options.dir);
21
+ validateAuthRuntime(runtimeDir);
22
+ header("Harness Data 认证配置", packageVersion(), [`运行目录:${runtimeDir}`]);
23
+
24
+ step(1, 2, "配置 CAS 凭证");
25
+ const casDir = await writeCasCredentials(runtimeDir, options);
26
+ blank();
27
+
28
+ step(2, 2, "刷新并校验访问 Token");
29
+ await configureTokens(runtimeDir, casDir);
30
+ blank();
31
+
32
+ ok("CAS 认证配置完成");
33
+ return { runtimeDir, casDir };
34
+ }
@@ -213,14 +213,18 @@ function casConfigDir(runtimeDir) {
213
213
  return path.join(runtimeDir, ".qdm-auth", "cas");
214
214
  }
215
215
 
216
- async function writeCasCredentials(runtimeDir, options = {}) {
216
+ export async function writeCasCredentials(runtimeDir, options = {}) {
217
217
  const username = options.casUsername || await ask("CAS 用户名:", options);
218
218
  const password = options.casPassword || await askSecret("CAS 密码:", options);
219
219
  if (!username || !password) throw new Error("CAS username and password are required");
220
220
  const dir = casConfigDir(runtimeDir);
221
221
  fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
222
222
  const env = { QDM_CAS_CONFIG_DIR: dir };
223
- await run(path.join(runtimeDir, "bin", binaryName("cas-cli")), ["config", "set-credentials", "--username", username, "--password", password], { cwd: runtimeDir, env });
223
+ await run(path.join(runtimeDir, "bin", binaryName("cas-cli")), ["config", "set-credentials", "--username", username, "--password", password], {
224
+ cwd: runtimeDir,
225
+ env,
226
+ sensitiveArgs: [5]
227
+ });
224
228
  ok("CAS 凭证已加密保存到 .qdm-auth/cas/credentials.enc");
225
229
  return dir;
226
230
  }
@@ -229,13 +233,13 @@ export async function configureTokens(runtimeDir, casDir) {
229
233
  const env = { QDM_CAS_CONFIG_DIR: casDir };
230
234
  const bin = (name) => path.join(runtimeDir, "bin", binaryName(name));
231
235
  const cmrToken = (await run(bin("cas-cli"), ["token", "--app", "cmr"], { cwd: runtimeDir, env })).stdout.trim();
232
- await run(bin("qdm-cmr-cli"), ["config", "set-token", cmrToken], { cwd: runtimeDir, env });
236
+ await run(bin("qdm-cmr-cli"), ["config", "set-token", cmrToken], { cwd: runtimeDir, env, sensitiveArgs: [2] });
233
237
  ok("CMR Token 已配置");
234
238
  const indicatorsToken = (await run(bin("cas-cli"), ["token", "--app", "indicators"], { cwd: runtimeDir, env })).stdout.trim();
235
- await run(bin("qdm-indicators-cli"), ["config", "set-token", indicatorsToken], { cwd: runtimeDir, env });
239
+ await run(bin("qdm-indicators-cli"), ["config", "set-token", indicatorsToken], { cwd: runtimeDir, env, sensitiveArgs: [2] });
236
240
  ok("Indicators Token 已配置");
237
241
  const sqlToken = (await run(bin("cas-cli"), ["token", "--app", "rtp"], { cwd: runtimeDir, env })).stdout.trim();
238
- await run(bin("qdm-sql-cli"), ["config", "set-token", sqlToken], { cwd: runtimeDir, env });
242
+ await run(bin("qdm-sql-cli"), ["config", "set-token", sqlToken], { cwd: runtimeDir, env, sensitiveArgs: [2] });
239
243
  ok("SQL Token 已配置");
240
244
  await run(bin("qdm-cmr-cli"), ["config", "check-token"], { cwd: runtimeDir, env });
241
245
  await run(bin("qdm-indicators-cli"), ["config", "check-token"], { cwd: runtimeDir, env });
package/src/lib/exec.js CHANGED
@@ -20,7 +20,9 @@ export function run(command, args = [], options = {}) {
20
20
  return;
21
21
  }
22
22
  const detail = stderr.trim() || stdout.trim();
23
- reject(new Error(`${command} ${args.join(" ")} failed${detail ? `: ${detail}` : ""}`));
23
+ const sensitiveArgs = new Set(options.sensitiveArgs || []);
24
+ const displayArgs = args.map((arg, index) => sensitiveArgs.has(index) ? "******" : arg);
25
+ reject(new Error(`${command} ${displayArgs.join(" ")} failed${detail ? `: ${detail}` : ""}`));
24
26
  });
25
27
  });
26
28
  }