@legioncodeinc/hive 0.6.0 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +5 -0
  2. package/dist/daemon/dashboard/app.js +25 -12
  3. package/dist/daemon/installer/detection.js +14 -2
  4. package/dist/daemon/installer/detection.js.map +1 -1
  5. package/dist/daemon/installer/products.d.ts +2 -5
  6. package/dist/daemon/installer/products.js +2 -4
  7. package/dist/daemon/installer/products.js.map +1 -1
  8. package/dist/dashboard/web/buzzing-screen.d.ts +8 -0
  9. package/dist/dashboard/web/buzzing-screen.js +77 -3
  10. package/dist/dashboard/web/buzzing-screen.js.map +1 -1
  11. package/dist/dashboard/web/onboarding/contracts.d.ts +37 -3
  12. package/dist/dashboard/web/onboarding/contracts.js +25 -17
  13. package/dist/dashboard/web/onboarding/contracts.js.map +1 -1
  14. package/dist/dashboard/web/onboarding/health-view.d.ts +10 -1
  15. package/dist/dashboard/web/onboarding/health-view.js +109 -25
  16. package/dist/dashboard/web/onboarding/health-view.js.map +1 -1
  17. package/dist/dashboard/web/onboarding/login-step.d.ts +6 -0
  18. package/dist/dashboard/web/onboarding/login-step.js +117 -4
  19. package/dist/dashboard/web/onboarding/login-step.js.map +1 -1
  20. package/dist/dashboard/web/onboarding/onboarding-screen.js +1 -1
  21. package/dist/dashboard/web/onboarding/onboarding-screen.js.map +1 -1
  22. package/dist/service/index.d.ts +7 -0
  23. package/dist/service/index.js +4 -1
  24. package/dist/service/index.js.map +1 -1
  25. package/dist/service/templates.d.ts +16 -2
  26. package/dist/service/templates.js +22 -7
  27. package/dist/service/templates.js.map +1 -1
  28. package/dist/service/windows-identity.d.ts +46 -0
  29. package/dist/service/windows-identity.js +76 -0
  30. package/dist/service/windows-identity.js.map +1 -0
  31. package/dist/shared/onboarding-types.d.ts +4 -0
  32. package/dist/shared/onboarding-types.js +4 -1
  33. package/dist/shared/onboarding-types.js.map +1 -1
  34. package/package.json +1 -1
@@ -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":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC,gEAAgE;AAChE,MAAM,CAAC,MAAM,mBAAmB,GAAG,kBAAkB,CAAC;AAgBtD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAsB;IACzD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,aAAa,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;AAC/E,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,0BAA0B;IACxC,OAAO,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,CAC1B,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QACtB,QAAQ,CAAC,UAAU,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YAChD,OAAO,CAAC,EAAE,EAAE,EAAE,KAAK,KAAK,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,IAAI,GAAG,MAAM;SAChB,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC;SAC/B,GAAG,EAAE,CAAC;IACT,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAEpC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC1C,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAEvC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC/D,OAAO,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACpD,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,sBAAsB,CAAC,GAAsB;IAC3D,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC;IAC9B,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC;IAC1B,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,EAAE,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC5F,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAAkC,EAAE;IAC7E,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACpC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,0BAA0B,EAAE,CAAC;IAEjE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAC1F,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACd,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,GAAG,CAAC;IAC/B,CAAC;IAED,OAAO,sBAAsB,CAAC,GAAG,CAAC,CAAC;AACrC,CAAC"}
@@ -11,11 +11,15 @@
11
11
  import type { FleetStatusResponse } from "./fleet-readiness.js";
12
12
  /** The four fleet product slugs (is-AC-3). The install allowlist is derived from this closed set. */
13
13
  export type ProductSlug = "honeycomb" | "doctor" | "hive" | "nectar";
14
+ /** The canonical runtime product list used by detect/onboarding contract code paths. */
15
+ export declare const PRODUCT_SLUGS: readonly ["honeycomb", "doctor", "hive", "nectar"];
14
16
  /**
15
17
  * The three installable-via-portal products. `hive` is intentionally excluded: it is the daemon
16
18
  * serving this very endpoint, so it is never a portal install target (a request for it is a 400).
17
19
  */
18
20
  export type InstallableProduct = "doctor" | "honeycomb" | "nectar";
21
+ /** The canonical installable product order for onboarding flows. */
22
+ export declare const INSTALLABLE_PRODUCTS: readonly ["doctor", "honeycomb", "nectar"];
19
23
  /** The closed set of install stages streamed over SSE (is-AC-11). Never a percentage (is-AC-12). */
20
24
  export type InstallStage = "resolving" | "downloading" | "linking" | "registering_service" | "completed" | "failed";
21
25
  /** The closed detection state set for a product (is-AC-2). */
@@ -8,5 +8,8 @@
8
8
  * Nothing in this module reaches persistence: the installer's only durable artifact is the
9
9
  * one-time onboarding token file, and even that is out of band from these wire types.
10
10
  */
11
- export {};
11
+ /** The canonical runtime product list used by detect/onboarding contract code paths. */
12
+ export const PRODUCT_SLUGS = ["honeycomb", "doctor", "hive", "nectar"];
13
+ /** The canonical installable product order for onboarding flows. */
14
+ export const INSTALLABLE_PRODUCTS = ["doctor", "honeycomb", "nectar"];
12
15
  //# sourceMappingURL=onboarding-types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"onboarding-types.js","sourceRoot":"","sources":["../../src/shared/onboarding-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
1
+ {"version":3,"file":"onboarding-types.js","sourceRoot":"","sources":["../../src/shared/onboarding-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,wFAAwF;AACxF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAC;AAQhF,oEAAoE;AACpE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAU,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legioncodeinc/hive",
3
- "version": "0.6.0",
3
+ "version": "0.6.3",
4
4
  "description": "Hive portal daemon",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "type": "module",