@wrongstack/cli 1.1.2 → 1.1.5
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/dist/{acp-HCGUTFNE.js → acp-NKUEYJDZ.js} +14 -5
- package/dist/acp-leader/acp-leader-confirm.d.ts +20 -0
- package/dist/acp-leader/acp-leader-context.d.ts +29 -0
- package/dist/acp-leader/acp-leader-fleet.d.ts +26 -0
- package/dist/acp-leader/acp-leader-host-binding.d.ts +17 -0
- package/dist/acp-leader/acp-leader-host.d.ts +82 -0
- package/dist/acp-leader/acp-leader-picker.d.ts +24 -0
- package/dist/acp-leader/acp-leader-provider.d.ts +85 -0
- package/dist/acp-leader/acp-leader-resume.d.ts +10 -0
- package/dist/acp-leader/acp-leader-stream.d.ts +83 -0
- package/dist/{auth-ANOVZVHE.js → auth-2ZG5DBHS.js} +62 -66
- package/dist/auth-menu/index.d.ts +1 -2
- package/dist/boot/dispatch-webui.d.ts +16 -0
- package/dist/boot/launch-menu-arrow.d.ts +20 -0
- package/dist/boot/launch-menu-types.d.ts +36 -0
- package/dist/boot/launch-menu.d.ts +1 -57
- package/dist/boot/tui-session-resume-rollback.d.ts +31 -0
- package/dist/{boot-auto-thin-7D4OVEWA.js → boot-auto-thin-N2CIGTXE.js} +3 -3
- package/dist/{chunk-TZPKOS5G.js → chunk-2XQ6SRKG.js} +2 -2
- package/dist/chunk-3LEIFO5D.js +65 -0
- package/dist/chunk-5SGMUDP5.js +752 -0
- package/dist/{chunk-3EXRPTAU.js → chunk-5TQ65PXQ.js} +17 -17
- package/dist/{chunk-GRAGMA4B.js → chunk-7BM4LGKQ.js} +18 -18
- package/dist/{chunk-VAQXOZKP.js → chunk-AJM4EFCM.js} +139 -136
- package/dist/{chunk-C2BBH4S4.js → chunk-E3MJFAFR.js} +2 -2
- package/dist/{chunk-5TRZZHMN.js → chunk-JCZ2D3VV.js} +4 -65
- package/dist/{chunk-AWRZWPJ3.js → chunk-JFYQGMMM.js} +99 -75
- package/dist/{chunk-BIGSVBPI.js → chunk-KNYIEQAY.js} +64 -61
- package/dist/chunk-LUEO5HLZ.js +50 -0
- package/dist/chunk-LYWOV4OX.js +252 -0
- package/dist/chunk-M7FNHCE3.js +2070 -0
- package/dist/{chunk-75OLD563.js → chunk-M7PSENGF.js} +3 -1
- package/dist/{chunk-NMXQFQ26.js → chunk-MEBXWI7U.js} +5 -5
- package/dist/{chunk-RAWHRRUJ.js → chunk-MKMM5RIW.js} +209 -201
- package/dist/{chunk-3R3OADC5.js → chunk-P7MEEUGT.js} +281 -252
- package/dist/chunk-QLYPIJ7X.js +258 -0
- package/dist/chunk-RN5CFAVQ.js +292 -0
- package/dist/{chunk-WDXNBYGD.js → chunk-TDP7CZGE.js} +6 -1
- package/dist/{chunk-6VPWQ4TG.js → chunk-UROB7MK5.js} +2 -1
- package/dist/chunk-VEESMPTX.js +254 -0
- package/dist/{chunk-IJLIAPCW.js → chunk-VPSAKGLK.js} +47 -47
- package/dist/{cli-context-YIT4FEDM.js → cli-context-CQYGIWOU.js} +254 -237
- package/dist/{cli-main-JIADJ5OL.js → cli-main-VRUJNUBX.js} +2081 -1594
- package/dist/cli-main-boot.d.ts +1 -1
- package/dist/config-doctor-known-keys.d.ts +33 -0
- package/dist/config-doctor.d.ts +2 -47
- package/dist/config-history-support.d.ts +36 -0
- package/dist/config-history.d.ts +1 -1
- package/dist/{config-transfer-Y7XJMJRN.js → config-transfer-B4GOZTFC.js} +2 -2
- package/dist/{execution-BAP566QC.js → execution-IV72RUSM.js} +5354 -5258
- package/dist/execution-tui.d.ts +30 -0
- package/dist/fleet/acp-live-steer.d.ts +28 -0
- package/dist/fleet/acp-permission-bridge.d.ts +49 -0
- package/dist/fleet/acp-quota-hold.d.ts +3 -0
- package/dist/fleet/acp-quota-reading.d.ts +3 -0
- package/dist/fleet/acp-turn-reminders.d.ts +15 -0
- package/dist/fleet/acp-wrongstack-bridge.d.ts +50 -0
- package/dist/fleet/host-acp.d.ts +23 -2
- package/dist/fleet/wrongforge-client.d.ts +116 -0
- package/dist/fleet/wrongforge-gateway.d.ts +20 -0
- package/dist/fleet/wrongforge-info.d.ts +32 -0
- package/dist/fleet/wrongforge-quota.d.ts +10 -0
- package/dist/fleet/wrongforge-runner.d.ts +37 -0
- package/dist/fleet/wrongforge-runtime.d.ts +10 -0
- package/dist/{hq-JD5AZVMG.js → hq-54PQYR5O.js} +311 -307
- package/dist/hq-server/sweeps.d.ts +28 -0
- package/dist/{hq-server-BI23EPM7.js → hq-server-YK7FBLL6.js} +3 -3
- package/dist/index.js +8 -5
- package/dist/mcp-22CFBX4H.js +236 -0
- package/dist/mcp-serve-project.d.ts +18 -0
- package/dist/mcp-serve.d.ts +0 -63
- package/dist/{modeldiag-HDIKG37X.js → modeldiag-5PBB777J.js} +4 -4
- package/dist/{per-subcommand-help-D6J4ZXW2.js → per-subcommand-help-MQGERD4E.js} +2 -2
- package/dist/plugin-llm-command.d.ts +9 -0
- package/dist/{plugin-usage-TYF5HY4K.js → plugin-usage-UWKYMNQU.js} +3 -3
- package/dist/{plugins-XGAXDLPT.js → plugins-VP7JQH47.js} +4 -4
- package/dist/{sdd-runtime-6MFUXWJK.js → sdd-runtime-HIJ4Z5TF.js} +2 -2
- package/dist/services/sdd/state.d.ts +2 -0
- package/dist/session-event-wiring-types.d.ts +62 -0
- package/dist/session-event-wiring.d.ts +2 -52
- package/dist/{sessions-config-SJVQXCIE.js → sessions-config-7MK742OW.js} +2 -2
- package/dist/short-circuit-flags-AGHURHMQ.js +11 -0
- package/dist/slash-commands/command-context-fleet.d.ts +187 -0
- package/dist/slash-commands/command-context-sdd-goal.d.ts +102 -0
- package/dist/slash-commands/command-context.d.ts +3 -282
- package/dist/slash-commands/project-switch-interactive.d.ts +11 -0
- package/dist/slash-commands/setmodel-helpers.d.ts +36 -0
- package/dist/subcommands/handlers/hq-token.d.ts +3 -0
- package/dist/subcommands/handlers/hq.d.ts +0 -21
- package/dist/subcommands/handlers/per-subcommand-help-operations.d.ts +8 -0
- package/dist/subcommands/handlers/tools-cli-args.d.ts +57 -0
- package/dist/subcommands/handlers/tools-cli.d.ts +5 -0
- package/dist/subcommands/handlers/tools-serve.d.ts +4 -0
- package/dist/{subcommands-VTMIZQBP.js → subcommands-OCJNO57E.js} +2 -2
- package/dist/tool-gateway-http.d.ts +30 -0
- package/dist/tool-gateway.d.ts +185 -0
- package/dist/tools-cli-44MLIUQO.js +509 -0
- package/dist/tools-serve-TRCET2M7.js +102 -0
- package/dist/{tools-skills-55QVTMSK.js → tools-skills-WDTMCE46.js} +7 -2
- package/dist/tuneup-runtime-checks.d.ts +7 -0
- package/dist/tuneup-types.d.ts +118 -0
- package/dist/tuneup.d.ts +3 -122
- package/dist/{typesafe-YBEADNAH.js → typesafe-QLSMFU7J.js} +1 -1
- package/dist/{version-help-RBZC5GZZ.js → version-help-X6CC4CFY.js} +2 -2
- package/dist/{webui-server-HIUY3RHD.js → webui-server-V2R5WQUK.js} +79 -3
- package/dist/wiring/provider-runtime-setup.d.ts +3 -1
- package/dist/wiring/session-runtime.d.ts +1 -1
- package/dist/wrongforge-gateway-UOFBK56J.js +92 -0
- package/dist/wrongforge-leader/wrongforge-leader-gateway.d.ts +9 -0
- package/dist/wrongforge-leader/wrongforge-leader-picker.d.ts +12 -0
- package/dist/wrongforge-leader/wrongforge-leader-provider.d.ts +49 -0
- package/package.json +34 -30
- package/dist/auth-menu/anthropic-oauth.d.ts +0 -43
- package/dist/chunk-XT3NAHRX.js +0 -337
- package/dist/chunk-ZNNFEKDZ.js +0 -319
- package/dist/mcp-2XWBJEQN.js +0 -464
- package/dist/short-circuit-flags-CPCT5MWB.js +0 -11
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
normalizeHqPublicOrigin,
|
|
9
9
|
resolveAuditActor
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-5TQ65PXQ.js";
|
|
11
11
|
import {
|
|
12
12
|
parseHqIpAllowlist
|
|
13
13
|
} from "./chunk-OGVSKS4Q.js";
|
|
@@ -18,13 +18,8 @@ import {
|
|
|
18
18
|
HQ_AUTH_FILE_VERSION,
|
|
19
19
|
HQ_CLI_DEFAULT_HOST,
|
|
20
20
|
HqInsecureExposureError,
|
|
21
|
-
isLoopbackHost
|
|
22
|
-
logHqAuthAudit,
|
|
23
|
-
mintHqToken,
|
|
24
|
-
mutateHqAuthFile,
|
|
25
|
-
readHqAuthFile as readHqAuthFile2
|
|
21
|
+
isLoopbackHost
|
|
26
22
|
} from "@wrongstack/core/hq";
|
|
27
|
-
import { expectDefined } from "@wrongstack/core/utils";
|
|
28
23
|
|
|
29
24
|
// src/subcommands/handlers/hq-alerts.ts
|
|
30
25
|
import * as fs from "node:fs/promises";
|
|
@@ -297,243 +292,14 @@ function printAuditHelp(deps) {
|
|
|
297
292
|
`);
|
|
298
293
|
}
|
|
299
294
|
|
|
300
|
-
// src/subcommands/handlers/hq.ts
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
return startServer(deps);
|
|
309
|
-
}
|
|
310
|
-
if (sub === "token") {
|
|
311
|
-
return hqTokenCmd(args.slice(1), deps);
|
|
312
|
-
}
|
|
313
|
-
if (sub === "audit") {
|
|
314
|
-
return hqAuditCmd(args.slice(1), deps);
|
|
315
|
-
}
|
|
316
|
-
if (sub === "alerts") {
|
|
317
|
-
return hqAlertsCmd(args.slice(1), deps);
|
|
318
|
-
}
|
|
319
|
-
if (sub === "service") {
|
|
320
|
-
const { hqServiceCmd } = await import("./hq-service-TQNPIRHL.js");
|
|
321
|
-
return hqServiceCmd(args.slice(1), deps);
|
|
322
|
-
}
|
|
323
|
-
if (sub === "help" || sub === "--help") {
|
|
324
|
-
printHelp(deps);
|
|
325
|
-
return 0;
|
|
326
|
-
}
|
|
327
|
-
deps.renderer.writeError(`Unknown hq subcommand: ${sub}
|
|
328
|
-
`);
|
|
329
|
-
printHelp(deps);
|
|
330
|
-
return 1;
|
|
331
|
-
};
|
|
332
|
-
async function startServer(deps) {
|
|
333
|
-
const { startHqServer } = await import("./hq-server-BI23EPM7.js");
|
|
334
|
-
const dataDir = resolveDataDir(deps);
|
|
335
|
-
const flags = deps.flags ?? {};
|
|
336
|
-
const rawPublicUrl = typeof flags["hq-public-url"] === "string" ? flags["hq-public-url"] : process.env.WRONGSTACK_HQ_PUBLIC_URL;
|
|
337
|
-
let publicOrigin;
|
|
338
|
-
if (rawPublicUrl !== void 0 && rawPublicUrl.trim() !== "") {
|
|
339
|
-
try {
|
|
340
|
-
publicOrigin = normalizeHqPublicOrigin(rawPublicUrl);
|
|
341
|
-
} catch (cause) {
|
|
342
|
-
deps.renderer.writeError(`${cause instanceof Error ? cause.message : String(cause)}
|
|
343
|
-
`);
|
|
344
|
-
return 1;
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
const host = typeof flags["host"] === "string" ? flags["host"] : publicOrigin !== void 0 ? "127.0.0.1" : HQ_CLI_DEFAULT_HOST;
|
|
348
|
-
const rawPort = typeof flags["port"] === "string" ? flags["port"].trim() : void 0;
|
|
349
|
-
const port = rawPort === void 0 ? 3499 : /^\d+$/.test(rawPort) ? Number(rawPort) : Number.NaN;
|
|
350
|
-
if (!Number.isInteger(port) || port < 0 || port > 65535) {
|
|
351
|
-
deps.renderer.writeError(`Invalid --port value: ${String(flags["port"])}
|
|
352
|
-
`);
|
|
353
|
-
return 1;
|
|
354
|
-
}
|
|
355
|
-
if (publicOrigin !== void 0 && !isLoopbackHost(host)) {
|
|
356
|
-
deps.renderer.writeError(
|
|
357
|
-
"Persistent public HQ requires a loopback bind. Remove --host or use --host 127.0.0.1.\n"
|
|
358
|
-
);
|
|
359
|
-
return 1;
|
|
360
|
-
}
|
|
361
|
-
const strictPort = flags["strict-port"] === true;
|
|
362
|
-
const open = flags["open"] === true;
|
|
363
|
-
let password;
|
|
364
|
-
try {
|
|
365
|
-
password = await resolveHqPasswordInput({
|
|
366
|
-
...typeof flags["password"] === "string" ? { explicitPassword: flags["password"] } : {}
|
|
367
|
-
});
|
|
368
|
-
} catch (cause) {
|
|
369
|
-
deps.renderer.writeError(`${cause instanceof Error ? cause.message : String(cause)}
|
|
370
|
-
`);
|
|
371
|
-
return 1;
|
|
372
|
-
}
|
|
373
|
-
const bootstrapPasswordOnly = /^(?:1|true)$/i.test(
|
|
374
|
-
process.env.WRONGSTACK_HQ_BOOTSTRAP_PASSWORD_ONLY?.trim() ?? ""
|
|
375
|
-
);
|
|
376
|
-
const allowInsecureOpen = flags["insecure-open"] === true;
|
|
377
|
-
const rawAllowlist = typeof flags["hq-allowlist"] === "string" ? flags["hq-allowlist"] : process.env.WRONGSTACK_HQ_ALLOWLIST;
|
|
378
|
-
let ipAllowlist;
|
|
379
|
-
try {
|
|
380
|
-
ipAllowlist = parseHqIpAllowlist(rawAllowlist);
|
|
381
|
-
} catch (cause) {
|
|
382
|
-
deps.renderer.writeError(`${cause instanceof Error ? cause.message : String(cause)}
|
|
383
|
-
`);
|
|
384
|
-
return 1;
|
|
385
|
-
}
|
|
386
|
-
const rawTtl = typeof flags["hq-token-ttl"] === "string" ? flags["hq-token-ttl"] : void 0;
|
|
387
|
-
let tokenTtlMs;
|
|
388
|
-
if (rawTtl !== void 0 && rawTtl.length > 0) {
|
|
389
|
-
const parsed = parseTokenTtlValue(rawTtl);
|
|
390
|
-
if (parsed.error) {
|
|
391
|
-
deps.renderer.writeError(`Invalid --hq-token-ttl: ${parsed.error}
|
|
392
|
-
`);
|
|
393
|
-
return 1;
|
|
394
|
-
}
|
|
395
|
-
tokenTtlMs = parsed.value;
|
|
396
|
-
}
|
|
397
|
-
const rawHops = typeof flags["hq-trusted-proxy-hops"] === "string" ? flags["hq-trusted-proxy-hops"] : void 0;
|
|
398
|
-
let trustedProxyHops;
|
|
399
|
-
if (rawHops !== void 0 && rawHops.length > 0) {
|
|
400
|
-
const parsed = Number.parseInt(rawHops, 10);
|
|
401
|
-
if (!Number.isFinite(parsed) || parsed < 0 || String(parsed) !== rawHops.trim()) {
|
|
402
|
-
deps.renderer.writeError(
|
|
403
|
-
"--hq-trusted-proxy-hops must be a non-negative integer (0 = ignore X-Forwarded-For).\n"
|
|
404
|
-
);
|
|
405
|
-
return 1;
|
|
406
|
-
}
|
|
407
|
-
trustedProxyHops = parsed;
|
|
408
|
-
}
|
|
409
|
-
if (password !== void 0 && password.length < 8) {
|
|
410
|
-
deps.renderer.writeError("HQ password must be at least 8 characters.\n");
|
|
411
|
-
return 1;
|
|
412
|
-
}
|
|
413
|
-
let handle;
|
|
414
|
-
try {
|
|
415
|
-
handle = await startHqServer({
|
|
416
|
-
host,
|
|
417
|
-
port,
|
|
418
|
-
strictPort,
|
|
419
|
-
dataDir,
|
|
420
|
-
allowInsecureOpen,
|
|
421
|
-
secureCookies: publicOrigin !== void 0,
|
|
422
|
-
requireBrowserAuth: publicOrigin !== void 0,
|
|
423
|
-
...password !== void 0 ? { password } : {},
|
|
424
|
-
...bootstrapPasswordOnly ? { bootstrapPasswordOnly: true } : {},
|
|
425
|
-
...tokenTtlMs !== void 0 ? { tokenTtlMs } : {},
|
|
426
|
-
...trustedProxyHops !== void 0 ? { trustedProxyHops } : {},
|
|
427
|
-
...ipAllowlist !== void 0 ? { ipAllowlist } : {}
|
|
428
|
-
});
|
|
429
|
-
} catch (err) {
|
|
430
|
-
if (err instanceof HqInsecureExposureError) {
|
|
431
|
-
deps.renderer.writeError(`${err.message}
|
|
432
|
-
`);
|
|
433
|
-
return 1;
|
|
434
|
-
}
|
|
435
|
-
throw err;
|
|
436
|
-
}
|
|
437
|
-
if (publicOrigin !== void 0) {
|
|
438
|
-
if (handle.firstRunSetup?.passwordMode !== true) {
|
|
439
|
-
await handle.close();
|
|
440
|
-
deps.renderer.writeError(
|
|
441
|
-
"Persistent public HQ requires password mode. Set WRONGSTACK_HQ_PASSWORD and retry.\n"
|
|
442
|
-
);
|
|
443
|
-
return 1;
|
|
444
|
-
}
|
|
445
|
-
handle.trustPublicOrigin(publicOrigin);
|
|
446
|
-
deps.renderer.write(`Public endpoint: ${publicOrigin}/
|
|
447
|
-
`);
|
|
448
|
-
deps.renderer.write(`Public mobile: ${publicOrigin}/mobile
|
|
449
|
-
`);
|
|
450
|
-
}
|
|
451
|
-
if (open) {
|
|
452
|
-
try {
|
|
453
|
-
const { openBrowser } = await import("@wrongstack/webui-server");
|
|
454
|
-
openBrowser(
|
|
455
|
-
publicOrigin ?? handle.firstRunSetup?.browserUrl ?? `http://${handle.host}:${handle.port}`
|
|
456
|
-
);
|
|
457
|
-
} catch {
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
writeStartupInfo(deps, handle);
|
|
461
|
-
deps.renderer.write(
|
|
462
|
-
ipAllowlist === void 0 ? "Network allowlist: disabled (authentication remains required when configured).\n" : `Network allowlist: active (${ipAllowlist.length} configured rule${ipAllowlist.length === 1 ? "" : "s"} + loopback).
|
|
463
|
-
`
|
|
464
|
-
);
|
|
465
|
-
await new Promise((resolve2) => {
|
|
466
|
-
const shutdown = async () => {
|
|
467
|
-
try {
|
|
468
|
-
await handle.close();
|
|
469
|
-
} catch (err) {
|
|
470
|
-
deps.renderer.write(`HQ server close error: ${String(err)}
|
|
471
|
-
`);
|
|
472
|
-
}
|
|
473
|
-
resolve2();
|
|
474
|
-
};
|
|
475
|
-
process.on("SIGINT", shutdown);
|
|
476
|
-
process.on("SIGTERM", shutdown);
|
|
477
|
-
});
|
|
478
|
-
return 0;
|
|
479
|
-
}
|
|
480
|
-
function writeStartupInfo(deps, handle) {
|
|
481
|
-
deps.renderer.write(`WrongStack HQ listening on http://${handle.host}:${handle.port}
|
|
482
|
-
`);
|
|
483
|
-
if (!handle.firstRunSetup) {
|
|
484
|
-
deps.renderer.write(`Client endpoint: ws://${handle.host}:${handle.port}/ws/client
|
|
485
|
-
`);
|
|
486
|
-
deps.renderer.write(`Browser endpoint: http://${handle.host}:${handle.port}
|
|
487
|
-
`);
|
|
488
|
-
deps.renderer.write(
|
|
489
|
-
`Mobile endpoint: http://${handle.host}:${handle.port}/mobile (password required)
|
|
490
|
-
`
|
|
491
|
-
);
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
if (process.env.WRONGSTACK_HQ_SUPPRESS_STARTUP_SECRETS === "1") {
|
|
495
|
-
deps.renderer.write(`Browser endpoint: http://${handle.host}:${handle.port}
|
|
496
|
-
`);
|
|
497
|
-
deps.renderer.write(
|
|
498
|
-
`Mobile endpoint: http://${handle.host}:${handle.port}/mobile (password required)
|
|
499
|
-
`
|
|
500
|
-
);
|
|
501
|
-
deps.renderer.write(`Client endpoint: ws://${handle.host}:${handle.port}/ws/client
|
|
502
|
-
`);
|
|
503
|
-
deps.renderer.write(
|
|
504
|
-
`Startup credentials suppressed; auth state is stored in ${handle.firstRunSetup.dataDir}.
|
|
505
|
-
`
|
|
506
|
-
);
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
509
|
-
const mobileUrl = new URL(handle.firstRunSetup.browserUrl);
|
|
510
|
-
mobileUrl.pathname = "/mobile";
|
|
511
|
-
mobileUrl.search = "";
|
|
512
|
-
mobileUrl.hash = "";
|
|
513
|
-
deps.renderer.write(`Browser endpoint: ${handle.firstRunSetup.browserUrl}
|
|
514
|
-
`);
|
|
515
|
-
deps.renderer.write(`Mobile endpoint: ${mobileUrl.toString()} (password required)
|
|
516
|
-
`);
|
|
517
|
-
deps.renderer.write(`Client endpoint: ${handle.firstRunSetup.clientUrl}
|
|
518
|
-
`);
|
|
519
|
-
deps.renderer.write(
|
|
520
|
-
handle.firstRunSetup.createdAuth ? `
|
|
521
|
-
First-run HQ auth created in ${handle.firstRunSetup.dataDir}
|
|
522
|
-
` : `
|
|
523
|
-
HQ auth loaded from ${handle.firstRunSetup.dataDir}
|
|
524
|
-
`
|
|
525
|
-
);
|
|
526
|
-
deps.renderer.write(`Start clients with:
|
|
527
|
-
`);
|
|
528
|
-
deps.renderer.write(` WRONGSTACK_HQ_URL=${handle.firstRunSetup.clientEnv.WRONGSTACK_HQ_URL}
|
|
529
|
-
`);
|
|
530
|
-
if (handle.firstRunSetup.clientEnv.WRONGSTACK_HQ_TOKEN) {
|
|
531
|
-
deps.renderer.write(
|
|
532
|
-
` WRONGSTACK_HQ_TOKEN=${handle.firstRunSetup.clientEnv.WRONGSTACK_HQ_TOKEN}
|
|
533
|
-
`
|
|
534
|
-
);
|
|
535
|
-
}
|
|
536
|
-
}
|
|
295
|
+
// src/subcommands/handlers/hq-token.ts
|
|
296
|
+
import {
|
|
297
|
+
logHqAuthAudit,
|
|
298
|
+
mintHqToken,
|
|
299
|
+
mutateHqAuthFile,
|
|
300
|
+
readHqAuthFile as readHqAuthFile2
|
|
301
|
+
} from "@wrongstack/core/hq";
|
|
302
|
+
import { expectDefined } from "@wrongstack/core/utils";
|
|
537
303
|
async function hqTokenCmd(args, deps) {
|
|
538
304
|
const action = args[0];
|
|
539
305
|
if (deps.flags?.["help"] === true || action === "help" || action === "--help") {
|
|
@@ -846,157 +612,395 @@ async function tokenRevoke(args, deps) {
|
|
|
846
612
|
);
|
|
847
613
|
return 0;
|
|
848
614
|
}
|
|
849
|
-
function
|
|
850
|
-
deps.renderer.write(`Usage: wstack hq <
|
|
615
|
+
function printTokenHelp(deps) {
|
|
616
|
+
deps.renderer.write(`Usage: wstack hq token <create | list | revoke>
|
|
851
617
|
`);
|
|
852
618
|
deps.renderer.write("\n");
|
|
853
|
-
deps.renderer.write(` wstack hq Start the HQ command center server.
|
|
854
|
-
`);
|
|
855
|
-
deps.renderer.write(` wstack hq serve Same as above (explicit form).
|
|
856
|
-
`);
|
|
857
619
|
deps.renderer.write(
|
|
858
|
-
` wstack hq token create [label] [--ttl <dur>]
|
|
620
|
+
` wstack hq token create [label] [--ttl <dur>] Mint a browser token (enters token mode).
|
|
859
621
|
`
|
|
860
622
|
);
|
|
861
623
|
deps.renderer.write(
|
|
862
|
-
` wstack hq token create --client [label] [--ttl <dur>]
|
|
624
|
+
` wstack hq token create --client [label] [--ttl <dur>] Mint a client token (/ws/client).
|
|
863
625
|
`
|
|
864
626
|
);
|
|
865
|
-
deps.renderer.write(` wstack hq token list List issued browser tokens.
|
|
866
|
-
`);
|
|
867
|
-
deps.renderer.write(` wstack hq token list --client List issued client tokens.
|
|
868
|
-
`);
|
|
869
627
|
deps.renderer.write(
|
|
870
|
-
` wstack hq token
|
|
628
|
+
` wstack hq token list List issued browser tokens (alias: ls).
|
|
871
629
|
`
|
|
872
630
|
);
|
|
873
|
-
deps.renderer.write(` wstack hq token revoke --client <id> Revoke a client token.
|
|
874
|
-
`);
|
|
875
631
|
deps.renderer.write(
|
|
876
|
-
` wstack hq
|
|
632
|
+
` wstack hq token list --client List issued client tokens.
|
|
877
633
|
`
|
|
878
634
|
);
|
|
879
635
|
deps.renderer.write(
|
|
880
|
-
` wstack hq
|
|
636
|
+
` wstack hq token revoke <id> Revoke a browser token (id prefix match).
|
|
881
637
|
`
|
|
882
638
|
);
|
|
883
|
-
deps.renderer.write(` wstack hq service status Show service and updater status.
|
|
884
|
-
`);
|
|
885
|
-
deps.renderer.write(` wstack hq service update Run the guarded update job now.
|
|
886
|
-
`);
|
|
887
639
|
deps.renderer.write(
|
|
888
|
-
` wstack hq
|
|
640
|
+
` wstack hq token revoke --client <id> Revoke a client token.
|
|
889
641
|
`
|
|
890
642
|
);
|
|
891
643
|
deps.renderer.write("\n");
|
|
892
|
-
deps.renderer.write(`
|
|
644
|
+
deps.renderer.write(`The token secret is printed once at create time and cannot be recovered
|
|
645
|
+
`);
|
|
646
|
+
deps.renderer.write(`from auth.json (only its SHA-256 verifier is persisted). Tokens live in
|
|
647
|
+
`);
|
|
648
|
+
deps.renderer.write(`<dataDir>/auth.json (default ~/.wrongstack/hq/auth.json).
|
|
649
|
+
`);
|
|
650
|
+
deps.renderer.write("\n");
|
|
651
|
+
deps.renderer.write(`Flags:
|
|
893
652
|
`);
|
|
894
653
|
deps.renderer.write(
|
|
895
654
|
` --data-dir <path> Override HQ data directory (default ~/.wrongstack/hq).
|
|
896
655
|
`
|
|
897
656
|
);
|
|
898
657
|
deps.renderer.write(
|
|
899
|
-
` --
|
|
658
|
+
` --client, -c Operate on client tokens instead of browser tokens.
|
|
900
659
|
`
|
|
901
660
|
);
|
|
902
661
|
deps.renderer.write(
|
|
903
|
-
` --
|
|
662
|
+
` --capabilities <csv> Comma-separated capability grants (browser: control.enqueue,control.approve; client: telemetry.publish,control.execute).
|
|
904
663
|
`
|
|
905
664
|
);
|
|
906
665
|
deps.renderer.write(
|
|
907
|
-
` --
|
|
666
|
+
` --ttl <duration> Stamp an expiresAt on the token (e.g. --ttl 1h, --ttl 7d, --ttl 3600s).
|
|
908
667
|
`
|
|
909
668
|
);
|
|
910
|
-
deps.renderer.write(
|
|
669
|
+
deps.renderer.write("\n");
|
|
670
|
+
deps.renderer.write(`Run \`wstack hq --help\` for the full HQ command list.
|
|
911
671
|
`);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// src/subcommands/handlers/hq.ts
|
|
675
|
+
var hqCmd = async (args, deps) => {
|
|
676
|
+
const sub = args[0];
|
|
677
|
+
if (deps.flags?.["help"] === true && (!sub || sub === "serve")) {
|
|
678
|
+
printHelp(deps);
|
|
679
|
+
return 0;
|
|
680
|
+
}
|
|
681
|
+
if (!sub || sub === "serve") {
|
|
682
|
+
return startServer(deps);
|
|
683
|
+
}
|
|
684
|
+
if (sub === "token") {
|
|
685
|
+
return hqTokenCmd(args.slice(1), deps);
|
|
686
|
+
}
|
|
687
|
+
if (sub === "audit") {
|
|
688
|
+
return hqAuditCmd(args.slice(1), deps);
|
|
689
|
+
}
|
|
690
|
+
if (sub === "alerts") {
|
|
691
|
+
return hqAlertsCmd(args.slice(1), deps);
|
|
692
|
+
}
|
|
693
|
+
if (sub === "service") {
|
|
694
|
+
const { hqServiceCmd } = await import("./hq-service-TQNPIRHL.js");
|
|
695
|
+
return hqServiceCmd(args.slice(1), deps);
|
|
696
|
+
}
|
|
697
|
+
if (sub === "help" || sub === "--help") {
|
|
698
|
+
printHelp(deps);
|
|
699
|
+
return 0;
|
|
700
|
+
}
|
|
701
|
+
deps.renderer.writeError(`Unknown hq subcommand: ${sub}
|
|
702
|
+
`);
|
|
703
|
+
printHelp(deps);
|
|
704
|
+
return 1;
|
|
705
|
+
};
|
|
706
|
+
async function startServer(deps) {
|
|
707
|
+
const { startHqServer } = await import("./hq-server-YK7FBLL6.js");
|
|
708
|
+
const dataDir = resolveDataDir(deps);
|
|
709
|
+
const flags = deps.flags ?? {};
|
|
710
|
+
const rawPublicUrl = typeof flags["hq-public-url"] === "string" ? flags["hq-public-url"] : process.env.WRONGSTACK_HQ_PUBLIC_URL;
|
|
711
|
+
let publicOrigin;
|
|
712
|
+
if (rawPublicUrl !== void 0 && rawPublicUrl.trim() !== "") {
|
|
713
|
+
try {
|
|
714
|
+
publicOrigin = normalizeHqPublicOrigin(rawPublicUrl);
|
|
715
|
+
} catch (cause) {
|
|
716
|
+
deps.renderer.writeError(`${cause instanceof Error ? cause.message : String(cause)}
|
|
717
|
+
`);
|
|
718
|
+
return 1;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
const host = typeof flags["host"] === "string" ? flags["host"] : publicOrigin !== void 0 ? "127.0.0.1" : HQ_CLI_DEFAULT_HOST;
|
|
722
|
+
const rawPort = typeof flags["port"] === "string" ? flags["port"].trim() : void 0;
|
|
723
|
+
const port = rawPort === void 0 ? 3499 : /^\d+$/.test(rawPort) ? Number(rawPort) : Number.NaN;
|
|
724
|
+
if (!Number.isInteger(port) || port < 0 || port > 65535) {
|
|
725
|
+
deps.renderer.writeError(`Invalid --port value: ${String(flags["port"])}
|
|
726
|
+
`);
|
|
727
|
+
return 1;
|
|
728
|
+
}
|
|
729
|
+
if (publicOrigin !== void 0 && !isLoopbackHost(host)) {
|
|
730
|
+
deps.renderer.writeError(
|
|
731
|
+
"Persistent public HQ requires a loopback bind. Remove --host or use --host 127.0.0.1.\n"
|
|
732
|
+
);
|
|
733
|
+
return 1;
|
|
734
|
+
}
|
|
735
|
+
const strictPort = flags["strict-port"] === true;
|
|
736
|
+
const open = flags["open"] === true;
|
|
737
|
+
let password;
|
|
738
|
+
try {
|
|
739
|
+
password = await resolveHqPasswordInput({
|
|
740
|
+
...typeof flags["password"] === "string" ? { explicitPassword: flags["password"] } : {}
|
|
741
|
+
});
|
|
742
|
+
} catch (cause) {
|
|
743
|
+
deps.renderer.writeError(`${cause instanceof Error ? cause.message : String(cause)}
|
|
744
|
+
`);
|
|
745
|
+
return 1;
|
|
746
|
+
}
|
|
747
|
+
const bootstrapPasswordOnly = /^(?:1|true)$/i.test(
|
|
748
|
+
process.env.WRONGSTACK_HQ_BOOTSTRAP_PASSWORD_ONLY?.trim() ?? ""
|
|
749
|
+
);
|
|
750
|
+
const allowInsecureOpen = flags["insecure-open"] === true;
|
|
751
|
+
const rawAllowlist = typeof flags["hq-allowlist"] === "string" ? flags["hq-allowlist"] : process.env.WRONGSTACK_HQ_ALLOWLIST;
|
|
752
|
+
let ipAllowlist;
|
|
753
|
+
try {
|
|
754
|
+
ipAllowlist = parseHqIpAllowlist(rawAllowlist);
|
|
755
|
+
} catch (cause) {
|
|
756
|
+
deps.renderer.writeError(`${cause instanceof Error ? cause.message : String(cause)}
|
|
757
|
+
`);
|
|
758
|
+
return 1;
|
|
759
|
+
}
|
|
760
|
+
const rawTtl = typeof flags["hq-token-ttl"] === "string" ? flags["hq-token-ttl"] : void 0;
|
|
761
|
+
let tokenTtlMs;
|
|
762
|
+
if (rawTtl !== void 0 && rawTtl.length > 0) {
|
|
763
|
+
const parsed = parseTokenTtlValue(rawTtl);
|
|
764
|
+
if (parsed.error) {
|
|
765
|
+
deps.renderer.writeError(`Invalid --hq-token-ttl: ${parsed.error}
|
|
766
|
+
`);
|
|
767
|
+
return 1;
|
|
768
|
+
}
|
|
769
|
+
tokenTtlMs = parsed.value;
|
|
770
|
+
}
|
|
771
|
+
const rawHops = typeof flags["hq-trusted-proxy-hops"] === "string" ? flags["hq-trusted-proxy-hops"] : void 0;
|
|
772
|
+
let trustedProxyHops;
|
|
773
|
+
if (rawHops !== void 0 && rawHops.length > 0) {
|
|
774
|
+
const parsed = Number.parseInt(rawHops, 10);
|
|
775
|
+
if (!Number.isFinite(parsed) || parsed < 0 || String(parsed) !== rawHops.trim()) {
|
|
776
|
+
deps.renderer.writeError(
|
|
777
|
+
"--hq-trusted-proxy-hops must be a non-negative integer (0 = ignore X-Forwarded-For).\n"
|
|
778
|
+
);
|
|
779
|
+
return 1;
|
|
780
|
+
}
|
|
781
|
+
trustedProxyHops = parsed;
|
|
782
|
+
}
|
|
783
|
+
if (password !== void 0 && password.length < 8) {
|
|
784
|
+
deps.renderer.writeError("HQ password must be at least 8 characters.\n");
|
|
785
|
+
return 1;
|
|
786
|
+
}
|
|
787
|
+
let handle;
|
|
788
|
+
try {
|
|
789
|
+
handle = await startHqServer({
|
|
790
|
+
host,
|
|
791
|
+
port,
|
|
792
|
+
strictPort,
|
|
793
|
+
dataDir,
|
|
794
|
+
allowInsecureOpen,
|
|
795
|
+
secureCookies: publicOrigin !== void 0,
|
|
796
|
+
requireBrowserAuth: publicOrigin !== void 0,
|
|
797
|
+
...password !== void 0 ? { password } : {},
|
|
798
|
+
...bootstrapPasswordOnly ? { bootstrapPasswordOnly: true } : {},
|
|
799
|
+
...tokenTtlMs !== void 0 ? { tokenTtlMs } : {},
|
|
800
|
+
...trustedProxyHops !== void 0 ? { trustedProxyHops } : {},
|
|
801
|
+
...ipAllowlist !== void 0 ? { ipAllowlist } : {}
|
|
802
|
+
});
|
|
803
|
+
} catch (err) {
|
|
804
|
+
if (err instanceof HqInsecureExposureError) {
|
|
805
|
+
deps.renderer.writeError(`${err.message}
|
|
806
|
+
`);
|
|
807
|
+
return 1;
|
|
808
|
+
}
|
|
809
|
+
throw err;
|
|
810
|
+
}
|
|
811
|
+
if (publicOrigin !== void 0) {
|
|
812
|
+
if (handle.firstRunSetup?.passwordMode !== true) {
|
|
813
|
+
await handle.close();
|
|
814
|
+
deps.renderer.writeError(
|
|
815
|
+
"Persistent public HQ requires password mode. Set WRONGSTACK_HQ_PASSWORD and retry.\n"
|
|
816
|
+
);
|
|
817
|
+
return 1;
|
|
818
|
+
}
|
|
819
|
+
handle.trustPublicOrigin(publicOrigin);
|
|
820
|
+
deps.renderer.write(`Public endpoint: ${publicOrigin}/
|
|
821
|
+
`);
|
|
822
|
+
deps.renderer.write(`Public mobile: ${publicOrigin}/mobile
|
|
823
|
+
`);
|
|
824
|
+
}
|
|
825
|
+
if (open) {
|
|
826
|
+
try {
|
|
827
|
+
const { openBrowser } = await import("@wrongstack/webui-server");
|
|
828
|
+
openBrowser(
|
|
829
|
+
publicOrigin ?? handle.firstRunSetup?.browserUrl ?? `http://${handle.host}:${handle.port}`
|
|
830
|
+
);
|
|
831
|
+
} catch {
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
writeStartupInfo(deps, handle);
|
|
912
835
|
deps.renderer.write(
|
|
913
|
-
`
|
|
836
|
+
ipAllowlist === void 0 ? "Network allowlist: disabled (authentication remains required when configured).\n" : `Network allowlist: active (${ipAllowlist.length} configured rule${ipAllowlist.length === 1 ? "" : "s"} + loopback).
|
|
914
837
|
`
|
|
915
838
|
);
|
|
916
|
-
|
|
839
|
+
await new Promise((resolve2) => {
|
|
840
|
+
const shutdown = async () => {
|
|
841
|
+
try {
|
|
842
|
+
await handle.close();
|
|
843
|
+
} catch (err) {
|
|
844
|
+
deps.renderer.write(`HQ server close error: ${String(err)}
|
|
917
845
|
`);
|
|
918
|
-
|
|
846
|
+
}
|
|
847
|
+
resolve2();
|
|
848
|
+
};
|
|
849
|
+
process.on("SIGINT", shutdown);
|
|
850
|
+
process.on("SIGTERM", shutdown);
|
|
851
|
+
});
|
|
852
|
+
return 0;
|
|
853
|
+
}
|
|
854
|
+
function writeStartupInfo(deps, handle) {
|
|
855
|
+
deps.renderer.write(`WrongStack HQ listening on http://${handle.host}:${handle.port}
|
|
856
|
+
`);
|
|
857
|
+
if (!handle.firstRunSetup) {
|
|
858
|
+
deps.renderer.write(`Client endpoint: ws://${handle.host}:${handle.port}/ws/client
|
|
859
|
+
`);
|
|
860
|
+
deps.renderer.write(`Browser endpoint: http://${handle.host}:${handle.port}
|
|
861
|
+
`);
|
|
862
|
+
deps.renderer.write(
|
|
863
|
+
`Mobile endpoint: http://${handle.host}:${handle.port}/mobile (password required)
|
|
864
|
+
`
|
|
865
|
+
);
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
if (process.env.WRONGSTACK_HQ_SUPPRESS_STARTUP_SECRETS === "1") {
|
|
869
|
+
deps.renderer.write(`Browser endpoint: http://${handle.host}:${handle.port}
|
|
870
|
+
`);
|
|
871
|
+
deps.renderer.write(
|
|
872
|
+
`Mobile endpoint: http://${handle.host}:${handle.port}/mobile (password required)
|
|
873
|
+
`
|
|
874
|
+
);
|
|
875
|
+
deps.renderer.write(`Client endpoint: ws://${handle.host}:${handle.port}/ws/client
|
|
876
|
+
`);
|
|
877
|
+
deps.renderer.write(
|
|
878
|
+
`Startup credentials suppressed; auth state is stored in ${handle.firstRunSetup.dataDir}.
|
|
879
|
+
`
|
|
880
|
+
);
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
const mobileUrl = new URL(handle.firstRunSetup.browserUrl);
|
|
884
|
+
mobileUrl.pathname = "/mobile";
|
|
885
|
+
mobileUrl.search = "";
|
|
886
|
+
mobileUrl.hash = "";
|
|
887
|
+
deps.renderer.write(`Browser endpoint: ${handle.firstRunSetup.browserUrl}
|
|
888
|
+
`);
|
|
889
|
+
deps.renderer.write(`Mobile endpoint: ${mobileUrl.toString()} (password required)
|
|
890
|
+
`);
|
|
891
|
+
deps.renderer.write(`Client endpoint: ${handle.firstRunSetup.clientUrl}
|
|
919
892
|
`);
|
|
920
893
|
deps.renderer.write(
|
|
921
|
-
|
|
894
|
+
handle.firstRunSetup.createdAuth ? `
|
|
895
|
+
First-run HQ auth created in ${handle.firstRunSetup.dataDir}
|
|
896
|
+
` : `
|
|
897
|
+
HQ auth loaded from ${handle.firstRunSetup.dataDir}
|
|
922
898
|
`
|
|
923
899
|
);
|
|
900
|
+
deps.renderer.write(`Start clients with:
|
|
901
|
+
`);
|
|
902
|
+
deps.renderer.write(` WRONGSTACK_HQ_URL=${handle.firstRunSetup.clientEnv.WRONGSTACK_HQ_URL}
|
|
903
|
+
`);
|
|
904
|
+
if (handle.firstRunSetup.clientEnv.WRONGSTACK_HQ_TOKEN) {
|
|
905
|
+
deps.renderer.write(
|
|
906
|
+
` WRONGSTACK_HQ_TOKEN=${handle.firstRunSetup.clientEnv.WRONGSTACK_HQ_TOKEN}
|
|
907
|
+
`
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
function printHelp(deps) {
|
|
912
|
+
deps.renderer.write(`Usage: wstack hq <serve | token | audit | service>
|
|
913
|
+
`);
|
|
914
|
+
deps.renderer.write("\n");
|
|
915
|
+
deps.renderer.write(` wstack hq Start the HQ command center server.
|
|
916
|
+
`);
|
|
917
|
+
deps.renderer.write(` wstack hq serve Same as above (explicit form).
|
|
918
|
+
`);
|
|
924
919
|
deps.renderer.write(
|
|
925
|
-
`
|
|
926
|
-
Default 0 (ignore the header). Set to the real hop count behind a tunnel,
|
|
927
|
-
otherwise every user shares one backoff bucket. Never guess high.
|
|
920
|
+
` wstack hq token create [label] [--ttl <dur>] Mint a browser token, enter token mode.
|
|
928
921
|
`
|
|
929
922
|
);
|
|
930
923
|
deps.renderer.write(
|
|
931
|
-
`
|
|
924
|
+
` wstack hq token create --client [label] [--ttl <dur>] Mint a client token (/ws/client).
|
|
932
925
|
`
|
|
933
926
|
);
|
|
934
|
-
deps.renderer.write(`
|
|
927
|
+
deps.renderer.write(` wstack hq token list List issued browser tokens.
|
|
928
|
+
`);
|
|
929
|
+
deps.renderer.write(` wstack hq token list --client List issued client tokens.
|
|
935
930
|
`);
|
|
936
931
|
deps.renderer.write(
|
|
937
|
-
`
|
|
932
|
+
` wstack hq token revoke <id> Revoke a browser token (id prefix match).
|
|
938
933
|
`
|
|
939
934
|
);
|
|
935
|
+
deps.renderer.write(` wstack hq token revoke --client <id> Revoke a client token.
|
|
936
|
+
`);
|
|
940
937
|
deps.renderer.write(
|
|
941
|
-
`
|
|
938
|
+
` wstack hq audit verify Re-derive auth.json contentHash for forensic comparison.
|
|
942
939
|
`
|
|
943
940
|
);
|
|
944
941
|
deps.renderer.write(
|
|
945
|
-
`
|
|
942
|
+
` wstack hq service install Install persistent Ubuntu/systemd service + updater timer.
|
|
946
943
|
`
|
|
947
944
|
);
|
|
948
|
-
deps.renderer.write(
|
|
949
|
-
deps.renderer.write(`auth.json schema version: ${HQ_AUTH_FILE_VERSION}.
|
|
945
|
+
deps.renderer.write(` wstack hq service status Show service and updater status.
|
|
950
946
|
`);
|
|
951
|
-
|
|
952
|
-
function printTokenHelp(deps) {
|
|
953
|
-
deps.renderer.write(`Usage: wstack hq token <create | list | revoke>
|
|
947
|
+
deps.renderer.write(` wstack hq service update Run the guarded update job now.
|
|
954
948
|
`);
|
|
955
|
-
deps.renderer.write("\n");
|
|
956
949
|
deps.renderer.write(
|
|
957
|
-
` wstack hq
|
|
950
|
+
` wstack hq service uninstall Remove units but preserve HQ data and secret file.
|
|
958
951
|
`
|
|
959
952
|
);
|
|
953
|
+
deps.renderer.write("\n");
|
|
954
|
+
deps.renderer.write(`Flags (apply to all subcommands):
|
|
955
|
+
`);
|
|
960
956
|
deps.renderer.write(
|
|
961
|
-
`
|
|
957
|
+
` --data-dir <path> Override HQ data directory (default ~/.wrongstack/hq).
|
|
962
958
|
`
|
|
963
959
|
);
|
|
964
960
|
deps.renderer.write(
|
|
965
|
-
`
|
|
961
|
+
` --host <ip> Bind host (default 0.0.0.0; use 127.0.0.1 for local-only).
|
|
966
962
|
`
|
|
967
963
|
);
|
|
968
964
|
deps.renderer.write(
|
|
969
|
-
`
|
|
965
|
+
` --tunnel Publish a temporary *.trycloudflare.com URL (requires cloudflared).
|
|
970
966
|
`
|
|
971
967
|
);
|
|
972
968
|
deps.renderer.write(
|
|
973
|
-
`
|
|
969
|
+
` --hq-public-url <https-origin> Trust a persistent TLS reverse-proxy origin; binds loopback and requires password mode.
|
|
974
970
|
`
|
|
975
971
|
);
|
|
972
|
+
deps.renderer.write(` --password <value> Set or rotate the browser login password.
|
|
973
|
+
`);
|
|
976
974
|
deps.renderer.write(
|
|
977
|
-
`
|
|
975
|
+
` --insecure-open Allow a non-loopback bind with no token/password set.
|
|
978
976
|
`
|
|
979
977
|
);
|
|
980
|
-
deps.renderer.write(
|
|
981
|
-
deps.renderer.write(`The token secret is printed once at create time and cannot be recovered
|
|
982
|
-
`);
|
|
983
|
-
deps.renderer.write(`from auth.json (only its SHA-256 verifier is persisted). Tokens live in
|
|
984
|
-
`);
|
|
985
|
-
deps.renderer.write(`<dataDir>/auth.json (default ~/.wrongstack/hq/auth.json).
|
|
978
|
+
deps.renderer.write(` --port <n> Bind port (default 3499).
|
|
986
979
|
`);
|
|
987
|
-
deps.renderer.write(
|
|
988
|
-
deps.renderer.write(`Flags:
|
|
980
|
+
deps.renderer.write(` --strict-port Fail if port is in use.
|
|
989
981
|
`);
|
|
990
982
|
deps.renderer.write(
|
|
991
|
-
` --
|
|
983
|
+
` --hq-token-ttl <dur> Stamp an expiresAt on first-run tokens (e.g. 1h, 7d, 3600s).
|
|
984
|
+
`
|
|
985
|
+
);
|
|
986
|
+
deps.renderer.write(
|
|
987
|
+
` --hq-trusted-proxy-hops <n> Trust the rightmost n X-Forwarded-For entries when rate-limiting logins.
|
|
988
|
+
Default 0 (ignore the header). Set to the real hop count behind a tunnel,
|
|
989
|
+
otherwise every user shares one backoff bucket. Never guess high.
|
|
992
990
|
`
|
|
993
991
|
);
|
|
992
|
+
deps.renderer.write(
|
|
993
|
+
` --hq-allowlist <csv> Optional source IP/CIDR allowlist (for example 203.0.113.4,10.0.0.0/8).
|
|
994
|
+
`
|
|
995
|
+
);
|
|
996
|
+
deps.renderer.write(` --open Open the dashboard in the default browser.
|
|
997
|
+
`);
|
|
994
998
|
deps.renderer.write(
|
|
995
999
|
` --client, -c Operate on client tokens instead of browser tokens.
|
|
996
1000
|
`
|
|
997
1001
|
);
|
|
998
1002
|
deps.renderer.write(
|
|
999
|
-
` --capabilities <csv>
|
|
1003
|
+
` --capabilities <csv> Token grants (browser: control.enqueue,control.approve; client: telemetry.publish,control.execute).
|
|
1000
1004
|
`
|
|
1001
1005
|
);
|
|
1002
1006
|
deps.renderer.write(
|
|
@@ -1004,10 +1008,10 @@ function printTokenHelp(deps) {
|
|
|
1004
1008
|
`
|
|
1005
1009
|
);
|
|
1006
1010
|
deps.renderer.write("\n");
|
|
1007
|
-
deps.renderer.write(`
|
|
1011
|
+
deps.renderer.write(`auth.json schema version: ${HQ_AUTH_FILE_VERSION}.
|
|
1008
1012
|
`);
|
|
1009
1013
|
}
|
|
1010
1014
|
export {
|
|
1011
1015
|
hqCmd
|
|
1012
1016
|
};
|
|
1013
|
-
//# sourceMappingURL=hq-
|
|
1017
|
+
//# sourceMappingURL=hq-54PQYR5O.js.map
|