@legioncodeinc/hive 0.5.1 → 0.6.2

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
@@ -157,13 +157,20 @@ The `hive` binary keeps a deliberately small surface. It's a portal daemon, not
157
157
 
158
158
  ```bash
159
159
  hive start # run the portal daemon on :3853 (the default verb)
160
+ hive stop # stop the portal daemon (service manager or direct SIGTERM)
160
161
  hive install-service # install the OS service unit (launchd / systemd / schtasks)
161
162
  hive uninstall-service # remove the service unit
163
+ hive uninstall # stop, remove service, registry entry, and hive state dir
162
164
  hive register # append Hive to Doctor's daemon registry
163
165
  ```
164
166
 
165
167
  That's the whole list, on purpose. Day to day you never touch it; the installer wires the service unit and registration, Doctor keeps the process alive, and you live in the browser.
166
168
 
169
+ Two behaviors worth knowing:
170
+
171
+ - **Hive owns sign-in for the fleet.** When Honeycomb or Nectar detect Hive on the machine, they never open a sign-in of their own; this dashboard's onboarding is the one login surface, and the workload daemons sit degraded until it writes the shared credentials, then recover on their own.
172
+ - **`uninstall` is surgical and honest.** It stops the daemon, removes the service unit (current `com.legioncode.hive` and legacy `thehive` labels), deletes Hive's entry from Doctor's registry without touching anyone else's, and removes `~/.apiary/hive`, nothing more. Already gone? It exits 0 and says so. For a full-machine wipe, see `doctor purge` or the one-command uninstall at [get.theapiary.sh](https://get.theapiary.sh).
173
+
167
174
  <img src="assets/brand/divider-minor.svg" width="100%" height="3">
168
175
 
169
176
  ## ✨ Open one URL, see the whole hive
@@ -13,7 +13,9 @@
13
13
  */
14
14
  import { type StartHiveOptions } from "./daemon/server.js";
15
15
  import { type RegistryUpsertOptions } from "./install/registry.js";
16
+ import { type StateDirFs } from "./install/state-dir.js";
16
17
  import { type ServiceModule } from "./service/index.js";
18
+ import { type FleetRootDeps } from "./shared/apiary-root.js";
17
19
  import { type EmitDeps } from "./telemetry/emit.js";
18
20
  /** A sink for user-facing output lines (defaults to `process.stdout`). */
19
21
  export type OutputWriter = (text: string) => void;
@@ -39,3 +41,21 @@ export interface RegisterCommandDeps {
39
41
  readonly out?: OutputWriter;
40
42
  }
41
43
  export declare function runRegisterCommand(deps?: RegisterCommandDeps): Promise<number>;
44
+ /** Injectable deps for the `stop` verb. */
45
+ export interface StopCommandDeps {
46
+ readonly service?: ServiceModule;
47
+ readonly fleetRoot?: FleetRootDeps;
48
+ readonly pidPath?: string;
49
+ readonly readPid?: (path: string) => number | null;
50
+ readonly isPidAlive?: (pid: number) => boolean;
51
+ readonly kill?: (pid: number, signal: NodeJS.Signals) => void;
52
+ readonly out?: OutputWriter;
53
+ }
54
+ export declare function runStopCommand(cliEntryPath: string, deps?: StopCommandDeps): Promise<number>;
55
+ /** Injectable deps for the `uninstall` verb. */
56
+ export interface UninstallCommandDeps extends ServiceCommandDeps {
57
+ readonly fleetRoot?: FleetRootDeps;
58
+ readonly stateDirFs?: StateDirFs;
59
+ readonly stop?: (cliEntryPath: string) => Promise<number>;
60
+ }
61
+ export declare function runUninstallCommand(cliEntryPath: string, deps?: UninstallCommandDeps): Promise<number>;
@@ -12,8 +12,11 @@
12
12
  * A telemetry failure NEVER changes a verb's exit code: emit helpers resolve, never reject.
13
13
  */
14
14
  import { startHive } from "./daemon/server.js";
15
- import { registerHiveWithDoctor } from "./install/registry.js";
15
+ import { deleteHiveFromDoctor, registerHiveWithDoctor, registryContainsHiveEntry } from "./install/registry.js";
16
+ import { hiveStateDirExists, removeHiveStateDir } from "./install/state-dir.js";
16
17
  import { createServiceModule } from "./service/index.js";
18
+ import { isPidAlive, readPidFile } from "./lock.js";
19
+ import { resolveHivePidPath } from "./shared/apiary-root.js";
17
20
  import { emitInstalled, emitUninstalled, recordStartLifecycle } from "./telemetry/emit.js";
18
21
  const defaultOut = (text) => {
19
22
  process.stdout.write(text);
@@ -63,7 +66,9 @@ export async function runUninstallServiceCommand(cliEntryPath, deps = {}) {
63
66
  const result = await service.uninstall();
64
67
  out(`${result.message}\n`);
65
68
  await uninstallTelemetry;
66
- return result.ok ? 0 : 1;
69
+ // M-2 / b-AC-6: the current unit having already been absent is a friendly no-op,
70
+ // not a failure - only a genuine deregister error should flip the exit code.
71
+ return result.ok || result.alreadyAbsent ? 0 : 1;
67
72
  }
68
73
  export async function runRegisterCommand(deps = {}) {
69
74
  const out = deps.out ?? defaultOut;
@@ -73,4 +78,90 @@ export async function runRegisterCommand(deps = {}) {
73
78
  : `Registered hive in ${registration.registryPath}\n`);
74
79
  return 0;
75
80
  }
81
+ function isHiveProcessRunning(deps) {
82
+ const pidPath = deps.pidPath ?? resolveHivePidPath(deps.fleetRoot);
83
+ const pid = (deps.readPid ?? readPidFile)(pidPath);
84
+ return pid !== null && (deps.isPidAlive ?? isPidAlive)(pid);
85
+ }
86
+ export async function runStopCommand(cliEntryPath, deps = {}) {
87
+ const out = deps.out ?? defaultOut;
88
+ const service = deps.service ?? createServiceModule({ execPath: cliEntryPath });
89
+ if (await service.isRegistered()) {
90
+ const result = await service.stop();
91
+ if (!result.ok && !isHiveProcessRunning(deps)) {
92
+ out("hive is not running.\n");
93
+ return 0;
94
+ }
95
+ out(`${result.message}\n`);
96
+ return result.ok ? 0 : 1;
97
+ }
98
+ if (!isHiveProcessRunning(deps)) {
99
+ out("hive is not running.\n");
100
+ return 0;
101
+ }
102
+ const pidPath = deps.pidPath ?? resolveHivePidPath(deps.fleetRoot);
103
+ const pid = (deps.readPid ?? readPidFile)(pidPath);
104
+ if (pid === null) {
105
+ out("hive is not running.\n");
106
+ return 0;
107
+ }
108
+ try {
109
+ (deps.kill ?? ((targetPid, signal) => process.kill(targetPid, signal)))(pid, "SIGTERM");
110
+ out(`Sent SIGTERM to hive (pid ${pid}).\n`);
111
+ return 0;
112
+ }
113
+ catch (error) {
114
+ out(`Could not stop hive: ${error instanceof Error ? error.message : "unknown error"}.\n`);
115
+ return 1;
116
+ }
117
+ }
118
+ async function hiveHasInstallArtifacts(cliEntryPath, deps) {
119
+ const service = deps.service ?? createServiceModule({ execPath: cliEntryPath });
120
+ if (await service.isRegistered())
121
+ return true;
122
+ if (registryContainsHiveEntry(deps.registry))
123
+ return true;
124
+ if (hiveStateDirExists(deps.fleetRoot, deps.stateDirFs))
125
+ return true;
126
+ return false;
127
+ }
128
+ export async function runUninstallCommand(cliEntryPath, deps = {}) {
129
+ const out = deps.out ?? defaultOut;
130
+ if (!(await hiveHasInstallArtifacts(cliEntryPath, deps))) {
131
+ out("hive is not installed; nothing to remove.\n");
132
+ return 0;
133
+ }
134
+ const stop = deps.stop ?? ((entryPath) => runStopCommand(entryPath, deps));
135
+ const service = deps.service ?? createServiceModule({ execPath: cliEntryPath });
136
+ const uninstallTelemetry = emitUninstalled(deps.telemetry);
137
+ const stopCode = await stop(cliEntryPath);
138
+ out(stopCode === 0 ? "Stopped hive daemon.\n" : "Stop step reported an issue; continuing uninstall.\n");
139
+ const serviceResult = await service.uninstall();
140
+ out(`${serviceResult.message}\n`);
141
+ const registryResult = deleteHiveFromDoctor(deps.registry);
142
+ out(registryResult.removed
143
+ ? `Removed hive from doctor registry (${registryResult.registryPaths.join(", ")}).\n`
144
+ : "No hive registry entry to remove.\n");
145
+ let stateRemoved = false;
146
+ try {
147
+ stateRemoved = removeHiveStateDir(deps.fleetRoot, deps.stateDirFs);
148
+ }
149
+ catch (error) {
150
+ out(`Could not remove hive state dir: ${error instanceof Error ? error.message : "unknown error"}.\n`);
151
+ await uninstallTelemetry;
152
+ return 1;
153
+ }
154
+ out(stateRemoved ? "Removed hive state dir.\n" : "No hive state dir to remove.\n");
155
+ await uninstallTelemetry;
156
+ // M-2 / b-AC-6: the current unit having already been absent (e.g. the stop step
157
+ // above already boot-ed it out on macOS) is a friendly no-op, not a failure.
158
+ // AC-9: never print the success line on the failure path - a contradictory
159
+ // "hive uninstalled." after a real deregister error hides the failure.
160
+ if (serviceResult.ok || serviceResult.alreadyAbsent) {
161
+ out("hive uninstalled.\n");
162
+ return 0;
163
+ }
164
+ out("hive uninstall completed with errors: the service unit may still be registered. Fix the error above and re-run 'hive uninstall'.\n");
165
+ return 1;
166
+ }
76
167
  //# sourceMappingURL=cli-commands.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli-commands.js","sourceRoot":"","sources":["../src/cli-commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli-commands.js","sourceRoot":"","sources":["../src/cli-commands.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { runInstallServiceCommand, runRegisterCommand, runStartCommand, runUninstallServiceCommand } from "./cli-commands.js";
3
+ import { runInstallServiceCommand, runRegisterCommand, runStartCommand, runStopCommand, runUninstallCommand, runUninstallServiceCommand } from "./cli-commands.js";
4
4
  import { DaemonAlreadyRunningError } from "./errors.js";
5
5
  function printUsage() {
6
- process.stderr.write("Usage: hive <start|install-service|uninstall-service|register>\n");
6
+ process.stderr.write("Usage: hive <start|stop|install-service|uninstall-service|uninstall|register>\n");
7
7
  }
8
8
  async function run() {
9
9
  const command = process.argv[2] ?? "start";
@@ -13,12 +13,18 @@ async function run() {
13
13
  case "start":
14
14
  process.exitCode = await runStartCommand();
15
15
  return;
16
+ case "stop":
17
+ process.exitCode = await runStopCommand(cliEntryPath);
18
+ return;
16
19
  case "install-service":
17
20
  process.exitCode = await runInstallServiceCommand(cliEntryPath);
18
21
  return;
19
22
  case "uninstall-service":
20
23
  process.exitCode = await runUninstallServiceCommand(cliEntryPath);
21
24
  return;
25
+ case "uninstall":
26
+ process.exitCode = await runUninstallCommand(cliEntryPath);
27
+ return;
22
28
  case "register":
23
29
  process.exitCode = await runRegisterCommand();
24
30
  return;
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EACf,0BAA0B,EAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAExD,SAAS,UAAU;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;AAC3F,CAAC;AAED,KAAK,UAAU,GAAG;IAChB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC;IAC3C,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEpD,IAAI,CAAC;QACH,QAAQ,OAAO,EAAE,CAAC;YAChB,KAAK,OAAO;gBACV,OAAO,CAAC,QAAQ,GAAG,MAAM,eAAe,EAAE,CAAC;gBAC3C,OAAO;YACT,KAAK,iBAAiB;gBACpB,OAAO,CAAC,QAAQ,GAAG,MAAM,wBAAwB,CAAC,YAAY,CAAC,CAAC;gBAChE,OAAO;YACT,KAAK,mBAAmB;gBACtB,OAAO,CAAC,QAAQ,GAAG,MAAM,0BAA0B,CAAC,YAAY,CAAC,CAAC;gBAClE,OAAO;YACT,KAAK,UAAU;gBACb,OAAO,CAAC,QAAQ,GAAG,MAAM,kBAAkB,EAAE,CAAC;gBAC9C,OAAO;YACT;gBACE,UAAU,EAAE,CAAC;gBACb,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;gBACrB,OAAO;QACX,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,yBAAyB,EAAE,CAAC;YAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;YAC3C,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;YAC3C,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,GAAG,EAAE,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,0BAA0B,EAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAExD,SAAS,UAAU;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iFAAiF,CAAC,CAAC;AAC1G,CAAC;AAED,KAAK,UAAU,GAAG;IAChB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC;IAC3C,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEpD,IAAI,CAAC;QACH,QAAQ,OAAO,EAAE,CAAC;YAChB,KAAK,OAAO;gBACV,OAAO,CAAC,QAAQ,GAAG,MAAM,eAAe,EAAE,CAAC;gBAC3C,OAAO;YACT,KAAK,MAAM;gBACT,OAAO,CAAC,QAAQ,GAAG,MAAM,cAAc,CAAC,YAAY,CAAC,CAAC;gBACtD,OAAO;YACT,KAAK,iBAAiB;gBACpB,OAAO,CAAC,QAAQ,GAAG,MAAM,wBAAwB,CAAC,YAAY,CAAC,CAAC;gBAChE,OAAO;YACT,KAAK,mBAAmB;gBACtB,OAAO,CAAC,QAAQ,GAAG,MAAM,0BAA0B,CAAC,YAAY,CAAC,CAAC;gBAClE,OAAO;YACT,KAAK,WAAW;gBACd,OAAO,CAAC,QAAQ,GAAG,MAAM,mBAAmB,CAAC,YAAY,CAAC,CAAC;gBAC3D,OAAO;YACT,KAAK,UAAU;gBACb,OAAO,CAAC,QAAQ,GAAG,MAAM,kBAAkB,EAAE,CAAC;gBAC9C,OAAO;YACT;gBACE,UAAU,EAAE,CAAC;gBACb,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;gBACrB,OAAO;QACX,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,yBAAyB,EAAE,CAAC;YAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;YAC3C,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;YAC3C,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,GAAG,EAAE,CAAC"}
@@ -1414,8 +1414,8 @@ export declare const SetupStateSchema: z.ZodObject<{
1414
1414
  migration: z.ZodOptional<z.ZodObject<{
1415
1415
  phase: z.ZodCatch<z.ZodEnum<{
1416
1416
  link: "link";
1417
- backup: "backup";
1418
1417
  uninstall: "uninstall";
1418
+ backup: "backup";
1419
1419
  done: "done";
1420
1420
  rolled_back: "rolled_back";
1421
1421
  }>>;
@@ -1452,8 +1452,8 @@ export declare const SetupMigrateSchema: z.ZodObject<{
1452
1452
  ok: z.ZodCatch<z.ZodBoolean>;
1453
1453
  phase: z.ZodCatch<z.ZodEnum<{
1454
1454
  link: "link";
1455
- backup: "backup";
1456
1455
  uninstall: "uninstall";
1456
+ backup: "backup";
1457
1457
  done: "done";
1458
1458
  rolled_back: "rolled_back";
1459
1459
  }>>;
@@ -32,4 +32,10 @@ export type RegistryDaemonEntry = Record<string, unknown> & {
32
32
  export declare function createNodeRegistryFs(): RegistryFs;
33
33
  export declare function buildHiveRegistryEntry(): RegistryDaemonEntry;
34
34
  export declare function registerHiveWithDoctor(options?: RegistryUpsertOptions): RegistryUpsertResult;
35
+ export interface RegistryDeleteResult {
36
+ readonly removed: boolean;
37
+ readonly registryPaths: readonly string[];
38
+ }
39
+ export declare function deleteHiveFromDoctor(options?: RegistryUpsertOptions): RegistryDeleteResult;
40
+ export declare function registryContainsHiveEntry(options?: RegistryUpsertOptions): boolean;
35
41
  export { resolveRegistryWritePath } from "../shared/registry-paths.js";
@@ -1,6 +1,7 @@
1
1
  import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
2
2
  import { dirname } from "node:path";
3
- import { resolveHiveRegistryPidPath } from "../shared/apiary-root.js";
3
+ import { resolveFleetRegistryPath, resolveHiveRegistryPidPath } from "../shared/apiary-root.js";
4
+ import { resolveLegacyDoctorRegistryPath } from "../shared/legacy-paths.js";
4
5
  import { resolveRegistryWritePath } from "../shared/registry-paths.js";
5
6
  // NOTE: there is deliberately NO exported DOCTOR_REGISTRY_PATH constant on the write side.
6
7
  // The write target is window-dependent (`resolveRegistryWritePath()` answers differently before
@@ -113,5 +114,71 @@ export function registerHiveWithDoctor(options = {}) {
113
114
  updatedExistingEntry: index >= 0
114
115
  };
115
116
  }
117
+ function registryHasHiveEntry(path, fs) {
118
+ const parsed = readRegistryDocument(path, fs);
119
+ return parsed.daemons.some((entry) => entry["name"] === HIVE_REGISTRY_NAME);
120
+ }
121
+ function deleteHiveEntryAtPath(path, fs) {
122
+ let parsed;
123
+ try {
124
+ parsed = readRegistryDocument(path, fs);
125
+ }
126
+ catch (error) {
127
+ const code = error.code;
128
+ if (code === "ENOENT")
129
+ return false;
130
+ throw error;
131
+ }
132
+ const index = parsed.daemons.findIndex((entry) => entry["name"] === HIVE_REGISTRY_NAME);
133
+ if (index < 0)
134
+ return false;
135
+ const nextDaemons = parsed.daemons.filter((_, entryIndex) => entryIndex !== index);
136
+ const nextRoot = { ...parsed.root, daemons: nextDaemons };
137
+ const serialized = `${JSON.stringify(nextRoot, null, 2)}\n`;
138
+ const tempPath = nextTempPath(path);
139
+ fs.mkdirp(dirname(path));
140
+ fs.writeFile(tempPath, serialized);
141
+ try {
142
+ fs.rename(tempPath, path);
143
+ }
144
+ catch (error) {
145
+ fs.removeFile(tempPath);
146
+ throw error;
147
+ }
148
+ return true;
149
+ }
150
+ export function deleteHiveFromDoctor(options = {}) {
151
+ const fs = options.fs ?? createNodeRegistryFs();
152
+ const explicitPath = options.registryPath;
153
+ const candidatePaths = explicitPath !== undefined
154
+ ? [explicitPath]
155
+ : [resolveRegistryWritePath(), resolveFleetRegistryPath(), resolveLegacyDoctorRegistryPath()];
156
+ const registryPaths = [];
157
+ for (const path of [...new Set(candidatePaths)]) {
158
+ if (deleteHiveEntryAtPath(path, fs))
159
+ registryPaths.push(path);
160
+ }
161
+ return {
162
+ removed: registryPaths.length > 0,
163
+ registryPaths
164
+ };
165
+ }
166
+ export function registryContainsHiveEntry(options = {}) {
167
+ const fs = options.fs ?? createNodeRegistryFs();
168
+ const explicitPath = options.registryPath;
169
+ const candidatePaths = explicitPath !== undefined
170
+ ? [explicitPath]
171
+ : [resolveRegistryWritePath(), resolveFleetRegistryPath(), resolveLegacyDoctorRegistryPath()];
172
+ for (const path of [...new Set(candidatePaths)]) {
173
+ try {
174
+ if (registryHasHiveEntry(path, fs))
175
+ return true;
176
+ }
177
+ catch {
178
+ // Unreadable registry files are treated as absent for uninstall no-op detection.
179
+ }
180
+ }
181
+ return false;
182
+ }
116
183
  export { resolveRegistryWritePath } from "../shared/registry-paths.js";
117
184
  //# sourceMappingURL=registry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/install/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAEvE,2FAA2F;AAC3F,gGAAgG;AAChG,gGAAgG;AAChG,mGAAmG;AAEnG,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAe,CAAC;AAClD,MAAM,CAAC,MAAM,wBAAwB,GAAG,8BAAuC,CAAC;AAChF,MAAM,CAAC,MAAM,sBAAsB,GAAG,0BAA0B,EAAE,CAAC;AACnE,MAAM,CAAC,MAAM,+BAA+B,GAAG,MAAe,CAAC;AAC/D,MAAM,CAAC,MAAM,8BAA8B,GAAG,MAAe,CAAC;AAC9D,MAAM,CAAC,MAAM,uCAAuC,GAAG,CAAU,CAAC;AAClE,MAAM,CAAC,MAAM,iCAAiC,GAAG,KAAc,CAAC;AAmChE,MAAM,UAAU,oBAAoB;IAClC,OAAO;QACL,QAAQ,CAAC,IAAY;YACnB,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpC,CAAC;QACD,MAAM,CAAC,IAAY;YACjB,2FAA2F;YAC3F,+EAA+E;YAC/E,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACpD,CAAC;QACD,SAAS,CAAC,IAAY,EAAE,OAAe;YACrC,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACvC,CAAC;QACD,MAAM,CAAC,IAAY,EAAE,EAAU;YAC7B,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACvB,CAAC;QACD,UAAU,CAAC,IAAY;YACrB,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChC,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAgC,CAAC;IAClH,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,qBAAqB,CAAC,GAAW;IACxC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACnC,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9B,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAEpD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;QACvC,CAAC,CAAC,UAAU;aACP,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;aAC/B,MAAM,CAAC,CAAC,KAAK,EAAoC,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC;QACxE,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,IAAI,EAAE,kBAAkB;QACxB,SAAS,EAAE,wBAAwB;QACnC,OAAO,EAAE,0BAA0B,EAAE;QACrC,eAAe,EAAE,+BAA+B;QAChD,cAAc,EAAE,8BAA8B;QAC9C,sBAAsB,EAAE,uCAAuC;QAC/D,iBAAiB,EAAE,iCAAiC;KACrD,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAY,EAAE,EAAc;IACxD,IAAI,CAAC;QACH,OAAO,qBAAqB,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;QACnD,IAAI,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QACxD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,YAAoB;IACxC,OAAO,GAAG,YAAY,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,UAAiC,EAAE;IACxE,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,wBAAwB,EAAE,CAAC;IACxE,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,oBAAoB,EAAE,CAAC;IAChD,MAAM,MAAM,GAAG,oBAAoB,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,sBAAsB,EAAE,CAAC;IAE3C,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,kBAAkB,CAAC,CAAC;IACrF,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACf,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,SAAS,EAAE,CAAC;IAC/D,CAAC;SAAM,CAAC;QACN,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC9B,CAAC;IAED,MAAM,QAAQ,GAA4B,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IACnF,MAAM,UAAU,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IAC5D,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAE5C,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;IACjC,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACnC,IAAI,CAAC;QACH,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACxB,MAAM,KAAK,CAAC;IACd,CAAC;IAED,OAAO;QACL,YAAY;QACZ,oBAAoB,EAAE,KAAK,IAAI,CAAC;KACjC,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/install/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { type FleetRootDeps } from "../shared/apiary-root.js";
2
+ export interface StateDirFs {
3
+ exists(path: string): boolean;
4
+ lstat(path: string): {
5
+ readonly isSymbolicLink: () => boolean;
6
+ };
7
+ removeDir(path: string): void;
8
+ }
9
+ export declare function createNodeStateDirFs(): StateDirFs;
10
+ export declare function removeHiveStateDir(deps?: FleetRootDeps, fs?: StateDirFs): boolean;
11
+ export declare function hiveStateDirExists(deps?: FleetRootDeps, fs?: StateDirFs): boolean;
@@ -0,0 +1,40 @@
1
+ import { existsSync, lstatSync, rmSync } from "node:fs";
2
+ import { isAbsolute, relative, resolve } from "node:path";
3
+ import { resolveFleetRoot, resolveHiveStateDir } from "../shared/apiary-root.js";
4
+ export function createNodeStateDirFs() {
5
+ return {
6
+ exists(path) {
7
+ return existsSync(path);
8
+ },
9
+ lstat(path) {
10
+ return lstatSync(path);
11
+ },
12
+ removeDir(path) {
13
+ rmSync(path, { recursive: true, force: true });
14
+ }
15
+ };
16
+ }
17
+ function isPathWithinRoot(targetPath, rootPath) {
18
+ const resolvedTarget = resolve(targetPath);
19
+ const resolvedRoot = resolve(rootPath);
20
+ const rel = relative(resolvedRoot, resolvedTarget);
21
+ return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
22
+ }
23
+ export function removeHiveStateDir(deps = {}, fs = createNodeStateDirFs()) {
24
+ const fleetRoot = resolveFleetRoot(deps);
25
+ const stateDir = resolveHiveStateDir(deps);
26
+ if (!isPathWithinRoot(stateDir, fleetRoot)) {
27
+ throw new Error(`Refusing to remove hive state dir outside the fleet root: ${stateDir}`);
28
+ }
29
+ if (!fs.exists(stateDir))
30
+ return false;
31
+ if (fs.lstat(stateDir).isSymbolicLink()) {
32
+ throw new Error(`Refusing to remove hive state dir because it is a symlink: ${stateDir}`);
33
+ }
34
+ fs.removeDir(stateDir);
35
+ return true;
36
+ }
37
+ export function hiveStateDirExists(deps = {}, fs = createNodeStateDirFs()) {
38
+ return fs.exists(resolveHiveStateDir(deps));
39
+ }
40
+ //# sourceMappingURL=state-dir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-dir.js","sourceRoot":"","sources":["../../src/install/state-dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1D,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAsB,MAAM,0BAA0B,CAAC;AAQrG,MAAM,UAAU,oBAAoB;IAClC,OAAO;QACL,MAAM,CAAC,IAAY;YACjB,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QACD,KAAK,CAAC,IAAY;YAChB,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;QACD,SAAS,CAAC,IAAY;YACpB,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,UAAkB,EAAE,QAAgB;IAC5D,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,QAAQ,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IACnD,OAAO,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAsB,EAAE,EAAE,KAAiB,oBAAoB,EAAE;IAClG,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAE3C,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,6DAA6D,QAAQ,EAAE,CAAC,CAAC;IAC3F,CAAC;IAED,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,8DAA8D,QAAQ,EAAE,CAAC,CAAC;IAC5F,CAAC;IAED,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACvB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAsB,EAAE,EAAE,KAAiB,oBAAoB,EAAE;IAClG,OAAO,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;AAC9C,CAAC"}
@@ -6,6 +6,7 @@ export interface ServiceCommand {
6
6
  export declare function launchdDomainTarget(uid: number): string;
7
7
  export declare function launchdServiceTarget(plan: ServicePlan, uid: number): string;
8
8
  export declare function installCommands(plan: ServicePlan, uid: number): readonly ServiceCommand[];
9
+ export declare function stopCommands(plan: ServicePlan, uid: number): readonly ServiceCommand[];
9
10
  export declare function uninstallCommands(plan: ServicePlan, uid: number): readonly ServiceCommand[];
10
11
  /**
11
12
  * The argv to deregister the PRE-decision-#32 unit names (`thehive` / `thehive.service`).
@@ -21,6 +21,16 @@ export function installCommands(plan, uid) {
21
21
  ];
22
22
  }
23
23
  }
24
+ export function stopCommands(plan, uid) {
25
+ switch (plan.manager) {
26
+ case "launchd":
27
+ return [{ command: "launchctl", args: ["bootout", launchdServiceTarget(plan, uid)] }];
28
+ case "systemd":
29
+ return [{ command: "systemctl", args: ["--user", "stop", SYSTEMD_UNIT_NAME] }];
30
+ case "schtasks":
31
+ return [{ command: "schtasks", args: ["/End", "/TN", WINDOWS_TASK_NAME] }];
32
+ }
33
+ }
24
34
  export function uninstallCommands(plan, uid) {
25
35
  switch (plan.manager) {
26
36
  case "launchd":
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/service/commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/service/commands.ts"],"names":[],"mappings":"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"}
@@ -15,14 +15,38 @@ export interface ServiceFs {
15
15
  mkdirp(path: string): void;
16
16
  writeFile(path: string, content: string): void;
17
17
  removeFile(path: string): void;
18
+ fileExists(path: string): boolean;
18
19
  }
19
20
  export interface ServiceResult {
20
21
  readonly ok: boolean;
21
22
  readonly message: string;
22
23
  }
24
+ /**
25
+ * The outcome of {@link ServiceModule.uninstall}, additionally classified so a
26
+ * caller can tell a genuine removal failure from the current unit simply
27
+ * having been absent already (M-2 / PRD-003b AC-9, b-AC-6): on macOS the
28
+ * `uninstall` verb runs `stop` (launchd `bootout`) before `service.uninstall()`
29
+ * issues its own `bootout` of the same unit, so the second call always finds
30
+ * "No such process" after a fully successful stop. A boot-resurrecting unit
31
+ * left behind by a swallowed "it was probably already gone" error is exactly
32
+ * the failure mode this classification exists to catch, so `alreadyAbsent`
33
+ * stays `false` for anything that does not match a known not-found signal.
34
+ */
35
+ export interface ServiceUninstallResult extends ServiceResult {
36
+ /**
37
+ * True when the manager reported the current unit was not registered/found
38
+ * rather than a real error (permission denied, manager unreachable, etc.).
39
+ * A true `alreadyAbsent` is a friendly no-op; `ok` stays false either way
40
+ * since nothing was actually removed by THIS call - callers should treat
41
+ * `alreadyAbsent === true` the same as `ok === true` for exit-code purposes.
42
+ */
43
+ readonly alreadyAbsent: boolean;
44
+ }
23
45
  export interface ServiceModule {
24
46
  install(): Promise<ServiceResult>;
25
- uninstall(): Promise<ServiceResult>;
47
+ stop(): Promise<ServiceResult>;
48
+ uninstall(): Promise<ServiceUninstallResult>;
49
+ isRegistered(): Promise<boolean>;
26
50
  }
27
51
  export interface ServiceModuleDeps {
28
52
  readonly execPath: string;
@@ -35,6 +59,13 @@ export interface ServiceModuleDeps {
35
59
  * against the plan's home; tests MUST inject a no-op so a fake `home` never touches real disk.
36
60
  */
37
61
  readonly migrateState?: (environment: ServiceEnvironment) => void;
62
+ /**
63
+ * Windows-only seam resolving the SID (or `domain\user` fallback) embedded as the schtasks
64
+ * `LogonTrigger`/`Principal` `UserId` (see `templates.ts` `renderScheduledTaskXml`). Defaults to
65
+ * the real {@link resolveWindowsUserId} (execFile of `whoami.exe`, never a shell); tests MUST
66
+ * inject a fixed value so a run never shells out. Never invoked for launchd/systemd plans.
67
+ */
68
+ readonly resolveWindowsUserId?: () => Promise<string | null>;
38
69
  }
39
70
  export declare function createExecFileRunner(): CommandRunner;
40
71
  export declare function createNodeServiceFs(): ServiceFs;
@@ -1,11 +1,12 @@
1
1
  import { execFile } from "node:child_process";
2
- import { mkdirSync, rmSync, writeFileSync } from "node:fs";
2
+ import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
3
3
  import { dirname } from "node:path";
4
4
  import { resolveStagedWindowsTaskPath } from "../shared/apiary-root.js";
5
5
  import { migrateHiveState } from "../shared/state-migration.js";
6
- import { installCommands, legacyUninstallCommands, uninstallCommands } from "./commands.js";
7
- import { legacyUnitPath, resolveServiceContext, resolveServicePlan } from "./platform.js";
6
+ import { installCommands, legacyUninstallCommands, stopCommands, uninstallCommands } from "./commands.js";
7
+ import { legacyUnitPath, LEGACY_WINDOWS_TASK_NAME, resolveServiceContext, resolveServicePlan, WINDOWS_TASK_NAME } from "./platform.js";
8
8
  import { renderUnit } from "./templates.js";
9
+ import { resolveWindowsUserId as resolveWindowsUserIdDefault } from "./windows-identity.js";
9
10
  const SERVICE_COMMAND_TIMEOUT_MS = 15_000;
10
11
  export function createExecFileRunner() {
11
12
  return {
@@ -40,6 +41,9 @@ export function createNodeServiceFs() {
40
41
  },
41
42
  removeFile(path) {
42
43
  rmSync(path, { force: true });
44
+ },
45
+ fileExists(path) {
46
+ return existsSync(path);
43
47
  }
44
48
  };
45
49
  }
@@ -67,13 +71,69 @@ function scopePhrase(plan) {
67
71
  }
68
72
  async function runAll(runner, commands) {
69
73
  let firstFailure = null;
74
+ let firstFailureResult = null;
70
75
  for (const command of commands) {
71
76
  const result = await runner.run(command.command, command.args, { timeoutMs: SERVICE_COMMAND_TIMEOUT_MS });
72
77
  if (!result.ok && firstFailure === null) {
73
78
  firstFailure = command;
79
+ firstFailureResult = result;
80
+ }
81
+ }
82
+ return { allOk: firstFailure === null, firstFailure, firstFailureResult };
83
+ }
84
+ /** Cap how much of a command's own output is ever echoed back in a result message. */
85
+ const MAX_FAILURE_DETAIL_CHARS = 200;
86
+ function lastNonEmptyLine(text) {
87
+ const lines = text
88
+ .split(/\r?\n/)
89
+ .map((line) => line.trim())
90
+ .filter((line) => line !== "");
91
+ return lines.length > 0 ? (lines[lines.length - 1] ?? null) : null;
92
+ }
93
+ /**
94
+ * Reduce a failed {@link CommandResult} to one short, secret-free line worth
95
+ * surfacing to the operator (e.g. "No such process", "Access is denied.").
96
+ * Prefers the runner's own `detail` (a spawn-error message); otherwise falls
97
+ * back to the last non-empty line of stderr, then stdout, since launchctl/
98
+ * systemctl/schtasks all print their real error there. A genuine failure must
99
+ * surface the underlying error rather than a generic "something failed" -
100
+ * that is what lets an operator tell a real problem from a no-op.
101
+ */
102
+ function describeFailure(result) {
103
+ if (result === null)
104
+ return "unknown error";
105
+ const candidate = result.detail ?? lastNonEmptyLine(result.stderr) ?? lastNonEmptyLine(result.stdout) ?? "unknown error";
106
+ return candidate.length > MAX_FAILURE_DETAIL_CHARS
107
+ ? `${candidate.slice(0, MAX_FAILURE_DETAIL_CHARS)}...`
108
+ : candidate;
109
+ }
110
+ /**
111
+ * True when a failed stop/uninstall command's result indicates the unit was
112
+ * already absent (not currently registered/running) rather than a genuine
113
+ * failure. Each service manager reports "not found" differently; launchd's
114
+ * `ESRCH`-derived exit code (3) is locale-independent so it is checked
115
+ * directly. Every manager additionally falls back to a broad, case-insensitive
116
+ * text match over stdout/stderr/detail. Anything that does not match is
117
+ * conservatively treated as a GENUINE failure (never silently swallowed) -
118
+ * this is the classification M-2 / AC-9 / b-AC-6 depend on.
119
+ */
120
+ function isAlreadyAbsentFailure(manager, result) {
121
+ if (result === null)
122
+ return false;
123
+ const text = `${result.detail ?? ""} ${result.stderr} ${result.stdout}`.toLowerCase();
124
+ const genericAbsent = /does not exist|cannot find|no such process|not[- ]loaded|could not find|not found/;
125
+ switch (manager) {
126
+ case "launchd":
127
+ return result.code === 3 || genericAbsent.test(text);
128
+ case "systemd":
129
+ return genericAbsent.test(text);
130
+ case "schtasks":
131
+ return genericAbsent.test(text);
132
+ default: {
133
+ const unreachable = manager;
134
+ return unreachable;
74
135
  }
75
136
  }
76
- return { allOk: firstFailure === null, firstFailure };
77
137
  }
78
138
  function withResolvedUnitPath(plan) {
79
139
  if (plan.manager !== "schtasks" || plan.unitPath !== "")
@@ -92,10 +152,36 @@ export function createServiceModule(deps) {
92
152
  ((env) => {
93
153
  migrateHiveState({ home: env.home, env: process.env });
94
154
  });
155
+ const resolveWindowsUserId = deps.resolveWindowsUserId ?? (() => resolveWindowsUserIdDefault());
95
156
  function plan() {
96
157
  return resolveServicePlan(environment);
97
158
  }
159
+ async function isRegisteredForPlan(resolvedPlan) {
160
+ if (resolvedPlan.manager === "schtasks") {
161
+ const current = await runner.run("schtasks", ["/Query", "/TN", WINDOWS_TASK_NAME], {
162
+ timeoutMs: SERVICE_COMMAND_TIMEOUT_MS
163
+ });
164
+ if (current.ok)
165
+ return true;
166
+ const legacy = await runner.run("schtasks", ["/Query", "/TN", LEGACY_WINDOWS_TASK_NAME], {
167
+ timeoutMs: SERVICE_COMMAND_TIMEOUT_MS
168
+ });
169
+ return legacy.ok;
170
+ }
171
+ if (resolvedPlan.unitPath !== "" && fs.fileExists(resolvedPlan.unitPath))
172
+ return true;
173
+ const legacyPath = legacyUnitPath(resolvedPlan);
174
+ return legacyPath !== "" && fs.fileExists(legacyPath);
175
+ }
98
176
  return {
177
+ async isRegistered() {
178
+ try {
179
+ return await isRegisteredForPlan(withResolvedUnitPath(plan()));
180
+ }
181
+ catch {
182
+ return false;
183
+ }
184
+ },
99
185
  async install() {
100
186
  let resolvedPlan;
101
187
  try {
@@ -125,7 +211,8 @@ export function createServiceModule(deps) {
125
211
  if (needsUnitFile) {
126
212
  try {
127
213
  fs.mkdirp(dirname(resolvedPlan.unitPath));
128
- fs.writeFile(resolvedPlan.unitPath, renderUnit(resolvedPlan));
214
+ const windowsUserId = resolvedPlan.manager === "schtasks" ? await resolveWindowsUserId() : null;
215
+ fs.writeFile(resolvedPlan.unitPath, renderUnit(resolvedPlan, process.env, windowsUserId));
129
216
  }
130
217
  catch (error) {
131
218
  return {
@@ -146,6 +233,39 @@ export function createServiceModule(deps) {
146
233
  message: `hive registered as a ${scopePhrase(resolvedPlan)} service and started. It will restart on crash and start on boot/login.`
147
234
  };
148
235
  },
236
+ async stop() {
237
+ let resolvedPlan;
238
+ try {
239
+ resolvedPlan = withResolvedUnitPath(plan());
240
+ }
241
+ catch (error) {
242
+ return {
243
+ ok: false,
244
+ message: `Could not stop hive service: ${error instanceof Error ? error.message : "unknown error"}.`
245
+ };
246
+ }
247
+ const { allOk, firstFailure, firstFailureResult } = await runAll(runner, stopCommands(resolvedPlan, uid));
248
+ if (!allOk) {
249
+ // M-2 posture applied to stop too: a manager reporting "already not running/
250
+ // loaded" (e.g. a repeat `hive stop`, or launchd having nothing left to boot
251
+ // out) is a friendly no-op, not a failure - there is nothing left to stop
252
+ // either way. A genuine failure still fails honestly with the real detail.
253
+ if (isAlreadyAbsentFailure(resolvedPlan.manager, firstFailureResult)) {
254
+ return {
255
+ ok: true,
256
+ message: `hive service was already stopped (${scopePhrase(resolvedPlan)}).`
257
+ };
258
+ }
259
+ return {
260
+ ok: false,
261
+ message: `A service-manager stop command (${firstFailure?.command ?? "unknown"}) reported an error: ${describeFailure(firstFailureResult)}.`
262
+ };
263
+ }
264
+ return {
265
+ ok: true,
266
+ message: `hive service stopped (${scopePhrase(resolvedPlan)}).`
267
+ };
268
+ },
149
269
  async uninstall() {
150
270
  let resolvedPlan;
151
271
  try {
@@ -154,25 +274,48 @@ export function createServiceModule(deps) {
154
274
  catch (error) {
155
275
  return {
156
276
  ok: false,
277
+ alreadyAbsent: false,
157
278
  message: `Could not unregister hive service: ${error instanceof Error ? error.message : "unknown error"}.`
158
279
  };
159
280
  }
160
- const { allOk, firstFailure } = await runAll(runner, uninstallCommands(resolvedPlan, uid));
281
+ // Legacy deregister is best-effort (same posture as install()): it is EXPECTED to fail
282
+ // when no pre-decision-#32 unit exists, so it must never fail the uninstall verdict.
283
+ // Only a current-unit deregister failure may flip `ok` to false.
284
+ await runAll(runner, legacyUninstallCommands(resolvedPlan, uid));
285
+ const { allOk, firstFailure, firstFailureResult } = await runAll(runner, uninstallCommands(resolvedPlan, uid));
161
286
  try {
162
287
  if (resolvedPlan.unitPath !== "")
163
288
  fs.removeFile(resolvedPlan.unitPath);
289
+ const legacyPath = legacyUnitPath(resolvedPlan);
290
+ if (legacyPath !== "")
291
+ fs.removeFile(legacyPath);
164
292
  }
165
293
  catch {
166
294
  // A stale unit file should not block uninstall feedback.
167
295
  }
168
296
  if (!allOk) {
297
+ // M-2: on macOS, `uninstall` runs stop (launchd `bootout`) before this current-unit
298
+ // `bootout`, so the unit is routinely already gone by the time this call runs - that
299
+ // is a friendly no-op (b-AC-6), not a failure, and must be classified as such rather
300
+ // than flipping the whole verb to exit 1 despite complete success (AC-9). A GENUINE
301
+ // failure (permission denied, manager unreachable, etc.) still fails honestly with
302
+ // the underlying error surfaced.
303
+ if (isAlreadyAbsentFailure(resolvedPlan.manager, firstFailureResult)) {
304
+ return {
305
+ ok: false,
306
+ alreadyAbsent: true,
307
+ message: `hive ${resolvedPlan.manager} unit was already absent (nothing to remove).`
308
+ };
309
+ }
169
310
  return {
170
311
  ok: false,
171
- message: `Removed hive unit file; a deregister command (${firstFailure?.command ?? "unknown"}) reported an error.`
312
+ alreadyAbsent: false,
313
+ message: `Removed hive unit file; a deregister command (${firstFailure?.command ?? "unknown"}) reported an error: ${describeFailure(firstFailureResult)}.`
172
314
  };
173
315
  }
174
316
  return {
175
317
  ok: true,
318
+ alreadyAbsent: false,
176
319
  message: `hive service unregistered (${scopePhrase(resolvedPlan)}). It will not start on next boot/login.`
177
320
  };
178
321
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/service/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/service/index.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,12 @@ import { type ServicePlan } from "./platform.js";
2
2
  export declare const HIVE_START_COMMAND: "start";
3
3
  export declare const RESTART_SEC: 5;
4
4
  export declare const WINDOWS_RESTART_INTERVAL: "PT1M";
5
+ /**
6
+ * The task action runs under `conhost.exe --headless` instead of `node.exe` directly, so the
7
+ * scheduled task never pops a visible console window at logon/run (proven empirically: the
8
+ * identical task ran with Last Result 0 and no window under this wrapper).
9
+ */
10
+ export declare const WINDOWS_CONHOST_COMMAND: "C:\\Windows\\System32\\conhost.exe";
5
11
  /**
6
12
  * rr-AC-10 / 010a implementation note: when the root resolved at render time differs from the
7
13
  * default `<home>/.apiary` (an `APIARY_HOME` or Linux XDG override is active), the installer must
@@ -24,6 +30,14 @@ export declare function renderSystemdUnit(plan: ServicePlan, env?: NodeJS.Proces
24
30
  * root at render time, but the task-started daemon resolves the default root unless the operator
25
31
  * sets APIARY_HOME machine-wide (setx / system properties). Recorded in PRD-010a implementation
26
32
  * notes; hive's Windows service is per-user InteractiveToken only, so no LocalSystem edge exists.
33
+ *
34
+ * `userId` (a SID or a `domain\user` fallback, resolved by the caller and passed in already
35
+ * escaped-ready) scopes the `LogonTrigger` and `Principal` to a concrete identity. An unscoped
36
+ * logon trigger/principal means "any user's logon", which a hardened Windows 11 25H2 machine
37
+ * (Administrator Protection enabled) refuses to register from a non-elevated shell. `null` renders
38
+ * with no `UserId`, matching prior behavior for machines where no identity could be resolved.
39
+ * `UserId` is placed first inside `<Principal>` and after `<Enabled>` inside `<LogonTrigger>` per
40
+ * the Task Scheduler schema's element ordering.
27
41
  */
28
- export declare function renderScheduledTaskXml(plan: ServicePlan): string;
29
- export declare function renderUnit(plan: ServicePlan, env?: NodeJS.ProcessEnv): string;
42
+ export declare function renderScheduledTaskXml(plan: ServicePlan, userId?: string | null): string;
43
+ export declare function renderUnit(plan: ServicePlan, env?: NodeJS.ProcessEnv, windowsUserId?: string | null): string;
@@ -4,6 +4,12 @@ import { resolveFleetRoot, resolveLaunchdLogPaths } from "../shared/apiary-root.
4
4
  export const HIVE_START_COMMAND = "start";
5
5
  export const RESTART_SEC = 5;
6
6
  export const WINDOWS_RESTART_INTERVAL = "PT1M";
7
+ /**
8
+ * The task action runs under `conhost.exe --headless` instead of `node.exe` directly, so the
9
+ * scheduled task never pops a visible console window at logon/run (proven empirically: the
10
+ * identical task ran with Last Result 0 and no window under this wrapper).
11
+ */
12
+ export const WINDOWS_CONHOST_COMMAND = "C:\\Windows\\System32\\conhost.exe";
7
13
  /**
8
14
  * rr-AC-10 / 010a implementation note: when the root resolved at render time differs from the
9
15
  * default `<home>/.apiary` (an `APIARY_HOME` or Linux XDG override is active), the installer must
@@ -99,10 +105,19 @@ WantedBy=default.target
99
105
  * root at render time, but the task-started daemon resolves the default root unless the operator
100
106
  * sets APIARY_HOME machine-wide (setx / system properties). Recorded in PRD-010a implementation
101
107
  * notes; hive's Windows service is per-user InteractiveToken only, so no LocalSystem edge exists.
108
+ *
109
+ * `userId` (a SID or a `domain\user` fallback, resolved by the caller and passed in already
110
+ * escaped-ready) scopes the `LogonTrigger` and `Principal` to a concrete identity. An unscoped
111
+ * logon trigger/principal means "any user's logon", which a hardened Windows 11 25H2 machine
112
+ * (Administrator Protection enabled) refuses to register from a non-elevated shell. `null` renders
113
+ * with no `UserId`, matching prior behavior for machines where no identity could be resolved.
114
+ * `UserId` is placed first inside `<Principal>` and after `<Enabled>` inside `<LogonTrigger>` per
115
+ * the Task Scheduler schema's element ordering.
102
116
  */
103
- export function renderScheduledTaskXml(plan) {
117
+ export function renderScheduledTaskXml(plan, userId = null) {
104
118
  const node = escapeXml(process.execPath);
105
119
  const exec = escapeXml(plan.execPath);
120
+ const userIdBlock = userId === null ? "" : `\n <UserId>${escapeXml(userId)}</UserId>`;
106
121
  return `<?xml version="1.0" encoding="UTF-16"?>
107
122
  <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
108
123
  <RegistrationInfo>
@@ -111,11 +126,11 @@ export function renderScheduledTaskXml(plan) {
111
126
  </RegistrationInfo>
112
127
  <Triggers>
113
128
  <LogonTrigger>
114
- <Enabled>true</Enabled>
129
+ <Enabled>true</Enabled>${userIdBlock}
115
130
  </LogonTrigger>
116
131
  </Triggers>
117
132
  <Principals>
118
- <Principal id="Author">
133
+ <Principal id="Author">${userIdBlock}
119
134
  <LogonType>InteractiveToken</LogonType>
120
135
  <RunLevel>LeastPrivilege</RunLevel>
121
136
  </Principal>
@@ -137,21 +152,21 @@ export function renderScheduledTaskXml(plan) {
137
152
  </Settings>
138
153
  <Actions Context="Author">
139
154
  <Exec>
140
- <Command>${node}</Command>
141
- <Arguments>"${exec}" ${HIVE_START_COMMAND}</Arguments>
155
+ <Command>${WINDOWS_CONHOST_COMMAND}</Command>
156
+ <Arguments>--headless "${node}" "${exec}" ${HIVE_START_COMMAND}</Arguments>
142
157
  </Exec>
143
158
  </Actions>
144
159
  </Task>
145
160
  `;
146
161
  }
147
- export function renderUnit(plan, env = process.env) {
162
+ export function renderUnit(plan, env = process.env, windowsUserId = null) {
148
163
  switch (plan.manager) {
149
164
  case "launchd":
150
165
  return renderLaunchdPlist(plan, env);
151
166
  case "systemd":
152
167
  return renderSystemdUnit(plan, env);
153
168
  case "schtasks":
154
- return renderScheduledTaskXml(plan);
169
+ return renderScheduledTaskXml(plan, windowsUserId);
155
170
  }
156
171
  }
157
172
  //# sourceMappingURL=templates.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/service/templates.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/service/templates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /** Matches a Windows SID string such as `S-1-5-21-...-1001`. */
2
+ export declare const WINDOWS_SID_PATTERN: RegExp;
3
+ export interface WhoamiResult {
4
+ readonly ok: boolean;
5
+ readonly stdout: string;
6
+ }
7
+ /** Injectable seam over the `whoami.exe` invocation (hermetic tests mirror production env). */
8
+ export type WhoamiRunner = (executable: string, args: readonly string[]) => Promise<WhoamiResult>;
9
+ /** Injectable seams for Windows identity resolution (hermetic tests mirror production env). */
10
+ export interface WindowsUserIdResolverDeps {
11
+ readonly env?: NodeJS.ProcessEnv;
12
+ readonly runWhoami?: WhoamiRunner;
13
+ }
14
+ /**
15
+ * Resolves `whoami.exe` under `%SystemRoot%\System32` explicitly (never bare `whoami`
16
+ * on PATH), so a git-bash `whoami` shadowing the real binary on some machines can never
17
+ * be picked up instead.
18
+ */
19
+ export declare function whoamiExecutablePath(env: NodeJS.ProcessEnv): string;
20
+ /** Real `whoami.exe` runner: execFile, never a shell. */
21
+ export declare function createExecFileWhoamiRunner(): WhoamiRunner;
22
+ /**
23
+ * Parses the SID out of `whoami /user /fo csv /nh` output, e.g.
24
+ * `"domain\user","S-1-5-21-...-1001"`. Takes the last non-empty line (defensive
25
+ * against a stray header row) and the last CSV field, strips surrounding quotes,
26
+ * and validates the shape. Returns `null` on anything that does not look like a SID.
27
+ */
28
+ export declare function parseWhoamiSid(stdout: string): string | null;
29
+ /** `${USERDOMAIN}\${USERNAME}`, or `null` when either is unset/empty. */
30
+ export declare function fallbackWindowsAccount(env: NodeJS.ProcessEnv): string | null;
31
+ /**
32
+ * Resolves the value to embed as the schtasks `LogonTrigger`/`Principal` `UserId`.
33
+ *
34
+ * On a hardened Windows 11 25H2 machine (Administrator Protection enabled), an
35
+ * unscoped `LogonTrigger`/`Principal` (no `UserId`, meaning "any user's logon") is
36
+ * exactly what makes `schtasks /Create` refuse registration from a non-elevated
37
+ * shell with "ERROR: Access is denied." Scoping both elements to a concrete
38
+ * identity is the fix.
39
+ *
40
+ * Resolution order: the current user's SID via `whoami.exe /user /fo csv /nh`
41
+ * (execFile, never a shell); falling back to `${USERDOMAIN}\${USERNAME}` when the
42
+ * SID cannot be determined; falling back to `null` (render with no `UserId`,
43
+ * today's unscoped behavior) when neither is available, so non-hardened machines
44
+ * keep working unchanged.
45
+ */
46
+ export declare function resolveWindowsUserId(deps?: WindowsUserIdResolverDeps): Promise<string | null>;
@@ -0,0 +1,76 @@
1
+ import { execFile } from "node:child_process";
2
+ import { win32 } from "node:path";
3
+ /** Matches a Windows SID string such as `S-1-5-21-...-1001`. */
4
+ export const WINDOWS_SID_PATTERN = /^S-1-\d+(-\d+)+$/;
5
+ /**
6
+ * Resolves `whoami.exe` under `%SystemRoot%\System32` explicitly (never bare `whoami`
7
+ * on PATH), so a git-bash `whoami` shadowing the real binary on some machines can never
8
+ * be picked up instead.
9
+ */
10
+ export function whoamiExecutablePath(env) {
11
+ return win32.join(env.SystemRoot ?? "C:\\Windows", "System32", "whoami.exe");
12
+ }
13
+ /** Real `whoami.exe` runner: execFile, never a shell. */
14
+ export function createExecFileWhoamiRunner() {
15
+ return (executable, args) => new Promise((resolve) => {
16
+ execFile(executable, [...args], (error, stdout) => {
17
+ resolve({ ok: error === null, stdout });
18
+ });
19
+ });
20
+ }
21
+ /**
22
+ * Parses the SID out of `whoami /user /fo csv /nh` output, e.g.
23
+ * `"domain\user","S-1-5-21-...-1001"`. Takes the last non-empty line (defensive
24
+ * against a stray header row) and the last CSV field, strips surrounding quotes,
25
+ * and validates the shape. Returns `null` on anything that does not look like a SID.
26
+ */
27
+ export function parseWhoamiSid(stdout) {
28
+ const line = stdout
29
+ .split(/\r?\n/)
30
+ .map((entry) => entry.trim())
31
+ .filter((entry) => entry !== "")
32
+ .pop();
33
+ if (line === undefined)
34
+ return null;
35
+ const fields = line.split(",");
36
+ const rawLast = fields[fields.length - 1];
37
+ if (rawLast === undefined)
38
+ return null;
39
+ const sid = rawLast.trim().replace(/^"/, "").replace(/"$/, "");
40
+ return WINDOWS_SID_PATTERN.test(sid) ? sid : null;
41
+ }
42
+ /** `${USERDOMAIN}\${USERNAME}`, or `null` when either is unset/empty. */
43
+ export function fallbackWindowsAccount(env) {
44
+ const domain = env.USERDOMAIN;
45
+ const user = env.USERNAME;
46
+ if (domain === undefined || domain === "" || user === undefined || user === "")
47
+ return null;
48
+ return `${domain}\\${user}`;
49
+ }
50
+ /**
51
+ * Resolves the value to embed as the schtasks `LogonTrigger`/`Principal` `UserId`.
52
+ *
53
+ * On a hardened Windows 11 25H2 machine (Administrator Protection enabled), an
54
+ * unscoped `LogonTrigger`/`Principal` (no `UserId`, meaning "any user's logon") is
55
+ * exactly what makes `schtasks /Create` refuse registration from a non-elevated
56
+ * shell with "ERROR: Access is denied." Scoping both elements to a concrete
57
+ * identity is the fix.
58
+ *
59
+ * Resolution order: the current user's SID via `whoami.exe /user /fo csv /nh`
60
+ * (execFile, never a shell); falling back to `${USERDOMAIN}\${USERNAME}` when the
61
+ * SID cannot be determined; falling back to `null` (render with no `UserId`,
62
+ * today's unscoped behavior) when neither is available, so non-hardened machines
63
+ * keep working unchanged.
64
+ */
65
+ export async function resolveWindowsUserId(deps = {}) {
66
+ const env = deps.env ?? process.env;
67
+ const runWhoami = deps.runWhoami ?? createExecFileWhoamiRunner();
68
+ const result = await runWhoami(whoamiExecutablePath(env), ["/user", "/fo", "csv", "/nh"]);
69
+ if (result.ok) {
70
+ const sid = parseWhoamiSid(result.stdout);
71
+ if (sid !== null)
72
+ return sid;
73
+ }
74
+ return fallbackWindowsAccount(env);
75
+ }
76
+ //# sourceMappingURL=windows-identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windows-identity.js","sourceRoot":"","sources":["../../src/service/windows-identity.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legioncodeinc/hive",
3
- "version": "0.5.1",
3
+ "version": "0.6.2",
4
4
  "description": "Hive portal daemon",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "type": "module",