@legioncodeinc/hive 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +1 -1
  2. package/dist/daemon/dashboard/app.js +11 -11
  3. package/dist/daemon/gate.d.ts +10 -6
  4. package/dist/daemon/gate.js +20 -8
  5. package/dist/daemon/gate.js.map +1 -1
  6. package/dist/daemon/installer/config.d.ts +2 -0
  7. package/dist/daemon/installer/config.js +5 -3
  8. package/dist/daemon/installer/config.js.map +1 -1
  9. package/dist/daemon/installer/funnel-telemetry.d.ts +17 -2
  10. package/dist/daemon/installer/funnel-telemetry.js +34 -3
  11. package/dist/daemon/installer/funnel-telemetry.js.map +1 -1
  12. package/dist/daemon/installer/routes.js +6 -2
  13. package/dist/daemon/installer/routes.js.map +1 -1
  14. package/dist/daemon/installer/security.d.ts +9 -2
  15. package/dist/daemon/installer/security.js +8 -0
  16. package/dist/daemon/installer/security.js.map +1 -1
  17. package/dist/daemon/installer/token.d.ts +8 -7
  18. package/dist/daemon/installer/token.js +40 -18
  19. package/dist/daemon/installer/token.js.map +1 -1
  20. package/dist/daemon/registry.d.ts +6 -0
  21. package/dist/daemon/registry.js +15 -17
  22. package/dist/daemon/registry.js.map +1 -1
  23. package/dist/daemon/server.d.ts +14 -0
  24. package/dist/daemon/server.js +19 -0
  25. package/dist/daemon/server.js.map +1 -1
  26. package/dist/daemon/setup-tenancy.d.ts +18 -0
  27. package/dist/daemon/setup-tenancy.js +37 -0
  28. package/dist/daemon/setup-tenancy.js.map +1 -0
  29. package/dist/dashboard/web/active-tenancy-display.d.ts +34 -0
  30. package/dist/dashboard/web/active-tenancy-display.js +84 -0
  31. package/dist/dashboard/web/active-tenancy-display.js.map +1 -0
  32. package/dist/dashboard/web/app.js +6 -2
  33. package/dist/dashboard/web/app.js.map +1 -1
  34. package/dist/dashboard/web/onboarding/contracts.d.ts +1 -1
  35. package/dist/dashboard/web/onboarding/contracts.js +9 -1
  36. package/dist/dashboard/web/onboarding/contracts.js.map +1 -1
  37. package/dist/dashboard/web/onboarding/login-step.d.ts +3 -4
  38. package/dist/dashboard/web/onboarding/login-step.js +12 -18
  39. package/dist/dashboard/web/onboarding/login-step.js.map +1 -1
  40. package/dist/dashboard/web/onboarding/onboarding-screen.d.ts +8 -4
  41. package/dist/dashboard/web/onboarding/onboarding-screen.js +90 -13
  42. package/dist/dashboard/web/onboarding/onboarding-screen.js.map +1 -1
  43. package/dist/dashboard/web/onboarding/tenancy-client.d.ts +19 -0
  44. package/dist/dashboard/web/onboarding/tenancy-client.js +84 -0
  45. package/dist/dashboard/web/onboarding/tenancy-client.js.map +1 -0
  46. package/dist/dashboard/web/onboarding/tenancy-contracts.d.ts +119 -0
  47. package/dist/dashboard/web/onboarding/tenancy-contracts.js +79 -0
  48. package/dist/dashboard/web/onboarding/tenancy-contracts.js.map +1 -0
  49. package/dist/dashboard/web/onboarding/tenancy-step.d.ts +32 -0
  50. package/dist/dashboard/web/onboarding/tenancy-step.js +223 -0
  51. package/dist/dashboard/web/onboarding/tenancy-step.js.map +1 -0
  52. package/dist/dashboard/web/pages/hive-graph.js +138 -43
  53. package/dist/dashboard/web/pages/hive-graph.js.map +1 -1
  54. package/dist/dashboard/web/wire.d.ts +111 -14
  55. package/dist/dashboard/web/wire.js +105 -0
  56. package/dist/dashboard/web/wire.js.map +1 -1
  57. package/dist/install/registry.d.ts +2 -2
  58. package/dist/install/registry.js +14 -7
  59. package/dist/install/registry.js.map +1 -1
  60. package/dist/lock.d.ts +5 -2
  61. package/dist/lock.js +36 -1
  62. package/dist/lock.js.map +1 -1
  63. package/dist/service/index.d.ts +5 -0
  64. package/dist/service/index.js +9 -1
  65. package/dist/service/index.js.map +1 -1
  66. package/dist/service/templates.d.ts +22 -3
  67. package/dist/service/templates.js +47 -10
  68. package/dist/service/templates.js.map +1 -1
  69. package/dist/shared/apiary-root.d.ts +28 -0
  70. package/dist/shared/apiary-root.js +71 -0
  71. package/dist/shared/apiary-root.js.map +1 -0
  72. package/dist/shared/constants.d.ts +0 -1
  73. package/dist/shared/constants.js +3 -5
  74. package/dist/shared/constants.js.map +1 -1
  75. package/dist/shared/legacy-paths.d.ts +22 -0
  76. package/dist/shared/legacy-paths.js +48 -0
  77. package/dist/shared/legacy-paths.js.map +1 -0
  78. package/dist/shared/registry-paths.d.ts +19 -0
  79. package/dist/shared/registry-paths.js +52 -0
  80. package/dist/shared/registry-paths.js.map +1 -0
  81. package/dist/shared/state-migration.d.ts +13 -0
  82. package/dist/shared/state-migration.js +92 -0
  83. package/dist/shared/state-migration.js.map +1 -0
  84. package/dist/telemetry/emit.d.ts +27 -14
  85. package/dist/telemetry/emit.js +20 -4
  86. package/dist/telemetry/emit.js.map +1 -1
  87. package/package.json +1 -1
@@ -2,9 +2,28 @@ 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
+ * rr-AC-10 / 010a implementation note: when the root resolved at render time differs from the
7
+ * default `<home>/.apiary` (an `APIARY_HOME` or Linux XDG override is active), the installer must
8
+ * pin `APIARY_HOME=<resolved root>` into the rendered unit so the manager-started daemon resolves
9
+ * the SAME root the unit's embedded paths were rendered with. Returns `null` for default installs
10
+ * (no pin rendered, no behavior change).
11
+ */
12
+ export declare function apiaryHomePin(plan: ServicePlan, env: NodeJS.ProcessEnv): string | null;
5
13
  export declare function quoteSystemdToken(value: string): string;
6
14
  export declare function escapeXml(value: string): string;
7
- export declare function renderLaunchdPlist(plan: ServicePlan): string;
8
- export declare function renderSystemdUnit(plan: ServicePlan): string;
15
+ export declare function renderLaunchdPlist(plan: ServicePlan, env?: NodeJS.ProcessEnv): string;
16
+ export declare function renderSystemdUnit(plan: ServicePlan, env?: NodeJS.ProcessEnv): string;
17
+ /**
18
+ * rr-AC-10 Windows caveat (documented limitation): the Task Scheduler task XML has no environment
19
+ * block, so an active `APIARY_HOME` override CANNOT be pinned into the task the way launchd
20
+ * (`EnvironmentVariables`) and systemd (`Environment=`) pin it. Wrapping the action in a shell to
21
+ * inject env is deliberately NOT done: the Arguments string is attacker-adjacent install input and
22
+ * must stay free of shell interpolation (the existing escapeXml metacharacter guard is the whole
23
+ * defense). Consequence: a Windows override install renders staged/unit paths under the override
24
+ * root at render time, but the task-started daemon resolves the default root unless the operator
25
+ * sets APIARY_HOME machine-wide (setx / system properties). Recorded in PRD-010a implementation
26
+ * notes; hive's Windows service is per-user InteractiveToken only, so no LocalSystem edge exists.
27
+ */
9
28
  export declare function renderScheduledTaskXml(plan: ServicePlan): string;
10
- export declare function renderUnit(plan: ServicePlan): string;
29
+ export declare function renderUnit(plan: ServicePlan, env?: NodeJS.ProcessEnv): string;
@@ -1,7 +1,20 @@
1
+ import { join } from "node:path";
1
2
  import { WINDOWS_TASK_NAME } from "./platform.js";
3
+ import { resolveFleetRoot, resolveLaunchdLogPaths } from "../shared/apiary-root.js";
2
4
  export const HIVE_START_COMMAND = "start";
3
5
  export const RESTART_SEC = 5;
4
6
  export const WINDOWS_RESTART_INTERVAL = "PT1M";
7
+ /**
8
+ * rr-AC-10 / 010a implementation note: when the root resolved at render time differs from the
9
+ * default `<home>/.apiary` (an `APIARY_HOME` or Linux XDG override is active), the installer must
10
+ * pin `APIARY_HOME=<resolved root>` into the rendered unit so the manager-started daemon resolves
11
+ * the SAME root the unit's embedded paths were rendered with. Returns `null` for default installs
12
+ * (no pin rendered, no behavior change).
13
+ */
14
+ export function apiaryHomePin(plan, env) {
15
+ const resolved = resolveFleetRoot({ home: plan.home, env });
16
+ return resolved === join(plan.home, ".apiary") ? null : resolved;
17
+ }
5
18
  export function quoteSystemdToken(value) {
6
19
  return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
7
20
  }
@@ -13,16 +26,27 @@ export function escapeXml(value) {
13
26
  .replaceAll('"', "&quot;")
14
27
  .replaceAll("'", "&apos;");
15
28
  }
16
- export function renderLaunchdPlist(plan) {
29
+ export function renderLaunchdPlist(plan, env = process.env) {
17
30
  const node = escapeXml(process.execPath);
18
31
  const exec = escapeXml(plan.execPath);
19
- const home = escapeXml(plan.home);
20
32
  const label = escapeXml(plan.label);
33
+ const logs = resolveLaunchdLogPaths({ home: plan.home, env });
34
+ const stdoutPath = escapeXml(logs.out);
35
+ const stderrPath = escapeXml(logs.err);
36
+ const pin = apiaryHomePin(plan, env);
37
+ const environmentBlock = pin === null
38
+ ? ""
39
+ : ` <key>EnvironmentVariables</key>
40
+ <dict>
41
+ <key>APIARY_HOME</key>
42
+ <string>${escapeXml(pin)}</string>
43
+ </dict>
44
+ `;
21
45
  return `<?xml version="1.0" encoding="UTF-8"?>
22
46
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
23
47
  <plist version="1.0">
24
48
  <dict>
25
- <key>Label</key>
49
+ ${environmentBlock} <key>Label</key>
26
50
  <string>${label}</string>
27
51
  <key>ProgramArguments</key>
28
52
  <array>
@@ -39,22 +63,24 @@ export function renderLaunchdPlist(plan) {
39
63
  <key>ProcessType</key>
40
64
  <string>Background</string>
41
65
  <key>StandardOutPath</key>
42
- <string>${home}/.honeycomb/hive/launchd.out.log</string>
66
+ <string>${stdoutPath}</string>
43
67
  <key>StandardErrorPath</key>
44
- <string>${home}/.honeycomb/hive/launchd.err.log</string>
68
+ <string>${stderrPath}</string>
45
69
  </dict>
46
70
  </plist>
47
71
  `;
48
72
  }
49
- export function renderSystemdUnit(plan) {
73
+ export function renderSystemdUnit(plan, env = process.env) {
50
74
  const execStart = `${quoteSystemdToken(process.execPath)} ${quoteSystemdToken(plan.execPath)} ${HIVE_START_COMMAND}`;
75
+ const pin = apiaryHomePin(plan, env);
76
+ const environmentLine = pin === null ? "" : `Environment=${quoteSystemdToken(`APIARY_HOME=${pin}`)}\n`;
51
77
  return `[Unit]
52
78
  Description=hive portal daemon
53
79
  After=network.target
54
80
 
55
81
  [Service]
56
82
  Type=simple
57
- ExecStart=${execStart}
83
+ ${environmentLine}ExecStart=${execStart}
58
84
  Restart=always
59
85
  RestartSec=${RESTART_SEC}
60
86
  StartLimitIntervalSec=0
@@ -63,6 +89,17 @@ StartLimitIntervalSec=0
63
89
  WantedBy=default.target
64
90
  `;
65
91
  }
92
+ /**
93
+ * rr-AC-10 Windows caveat (documented limitation): the Task Scheduler task XML has no environment
94
+ * block, so an active `APIARY_HOME` override CANNOT be pinned into the task the way launchd
95
+ * (`EnvironmentVariables`) and systemd (`Environment=`) pin it. Wrapping the action in a shell to
96
+ * inject env is deliberately NOT done: the Arguments string is attacker-adjacent install input and
97
+ * must stay free of shell interpolation (the existing escapeXml metacharacter guard is the whole
98
+ * defense). Consequence: a Windows override install renders staged/unit paths under the override
99
+ * root at render time, but the task-started daemon resolves the default root unless the operator
100
+ * sets APIARY_HOME machine-wide (setx / system properties). Recorded in PRD-010a implementation
101
+ * notes; hive's Windows service is per-user InteractiveToken only, so no LocalSystem edge exists.
102
+ */
66
103
  export function renderScheduledTaskXml(plan) {
67
104
  const node = escapeXml(process.execPath);
68
105
  const exec = escapeXml(plan.execPath);
@@ -107,12 +144,12 @@ export function renderScheduledTaskXml(plan) {
107
144
  </Task>
108
145
  `;
109
146
  }
110
- export function renderUnit(plan) {
147
+ export function renderUnit(plan, env = process.env) {
111
148
  switch (plan.manager) {
112
149
  case "launchd":
113
- return renderLaunchdPlist(plan);
150
+ return renderLaunchdPlist(plan, env);
114
151
  case "systemd":
115
- return renderSystemdUnit(plan);
152
+ return renderSystemdUnit(plan, env);
116
153
  case "schtasks":
117
154
  return renderScheduledTaskXml(plan);
118
155
  }
@@ -1 +1 @@
1
- {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/service/templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,eAAe,CAAC;AAEpE,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAgB,CAAC;AACnD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAU,CAAC;AACtC,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAe,CAAC;AAExD,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,KAAK;SACT,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAiB;IAClD,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,OAAO;;;;;WAKE,KAAK;;;YAGJ,IAAI;YACJ,IAAI;YACJ,kBAAkB;;;;;;;YAOlB,WAAW;;;;WAIZ,IAAI;;WAEJ,IAAI;;;CAGd,CAAC;AACF,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAiB;IACjD,MAAM,SAAS,GAAG,GAAG,iBAAiB,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,kBAAkB,EAAE,CAAC;IACrH,OAAO;;;;;;YAMG,SAAS;;aAER,WAAW;;;;;CAKvB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,IAAiB;IACtD,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtC,OAAO;;;;aAII,SAAS,CAAC,iBAAiB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;kBAwBvB,wBAAwB;;;;;;iBAMzB,IAAI;oBACD,IAAI,KAAK,kBAAkB;;;;CAI9C,CAAC;AACF,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAiB;IAC1C,QAAQ,IAAI,CAAC,OAAO,EAAE,CAAC;QACrB,KAAK,SAAS;YACZ,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAClC,KAAK,SAAS;YACZ,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACjC,KAAK,UAAU;YACb,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/service/templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,iBAAiB,EAAoB,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEpF,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAgB,CAAC;AACnD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAU,CAAC;AACtC,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAe,CAAC;AAExD;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAiB,EAAE,GAAsB;IACrE,MAAM,QAAQ,GAAG,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5D,OAAO,QAAQ,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,KAAK;SACT,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAiB,EAAE,MAAyB,OAAO,CAAC,GAAG;IACxF,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,sBAAsB,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACrC,MAAM,gBAAgB,GACpB,GAAG,KAAK,IAAI;QACV,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC;;;YAGI,SAAS,CAAC,GAAG,CAAC;;CAEzB,CAAC;IACA,OAAO;;;;EAIP,gBAAgB;WACP,KAAK;;;YAGJ,IAAI;YACJ,IAAI;YACJ,kBAAkB;;;;;;;YAOlB,WAAW;;;;WAIZ,UAAU;;WAEV,UAAU;;;CAGpB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAiB,EAAE,MAAyB,OAAO,CAAC,GAAG;IACvF,MAAM,SAAS,GAAG,GAAG,iBAAiB,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,kBAAkB,EAAE,CAAC;IACrH,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACrC,MAAM,eAAe,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,iBAAiB,CAAC,eAAe,GAAG,EAAE,CAAC,IAAI,CAAC;IACvG,OAAO;;;;;;EAMP,eAAe,aAAa,SAAS;;aAE1B,WAAW;;;;;CAKvB,CAAC;AACF,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAiB;IACtD,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtC,OAAO;;;;aAII,SAAS,CAAC,iBAAiB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;kBAwBvB,wBAAwB;;;;;;iBAMzB,IAAI;oBACD,IAAI,KAAK,kBAAkB;;;;CAI9C,CAAC;AACF,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAiB,EAAE,MAAyB,OAAO,CAAC,GAAG;IAChF,QAAQ,IAAI,CAAC,OAAO,EAAE,CAAC;QACrB,KAAK,SAAS;YACZ,OAAO,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACvC,KAAK,SAAS;YACZ,OAAO,iBAAiB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACtC,KAAK,UAAU;YACb,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ /** Injectable seams for fleet-root resolution (hermetic tests mirror production env). */
2
+ export interface FleetRootDeps {
3
+ readonly env?: NodeJS.ProcessEnv;
4
+ readonly platform?: NodeJS.Platform;
5
+ readonly home?: string;
6
+ }
7
+ /**
8
+ * Canonical fleet root chain (ADR-0005 / superproject ADR-0003 "Resolved decisions"):
9
+ * APIARY_HOME > Linux XDG_STATE_HOME/apiary (only when XDG is explicitly set) > <home>/.apiary.
10
+ * Anchored on `home` (default `os.homedir()`); never reads `process.cwd()`.
11
+ */
12
+ export declare function resolveFleetRoot(deps?: FleetRootDeps): string;
13
+ /** Per-product hive state directory: `<fleetRoot>/hive`. */
14
+ export declare function resolveHiveStateDir(deps?: FleetRootDeps): string;
15
+ /** Doctor-owned cross-daemon registry at the fleet root. */
16
+ export declare function resolveFleetRegistryPath(deps?: FleetRootDeps): string;
17
+ /** Fleet-root shared install id (doctor/installer-managed; hive read-only). */
18
+ export declare function resolveSharedInstallIdPath(deps?: FleetRootDeps): string;
19
+ export declare function resolveHivePidPath(deps?: FleetRootDeps): string;
20
+ export declare function resolveHiveLockPath(deps?: FleetRootDeps): string;
21
+ export declare function resolveOnboardingTokenPath(deps?: FleetRootDeps): string;
22
+ export declare function resolveStagedWindowsTaskPath(deps?: FleetRootDeps): string;
23
+ export declare function resolveLaunchdLogPaths(deps?: FleetRootDeps): {
24
+ readonly out: string;
25
+ readonly err: string;
26
+ };
27
+ /** Absolute pidPath written into hive's registry entry (ADR Resolved decision 4). */
28
+ export declare function resolveHiveRegistryPidPath(deps?: FleetRootDeps): string;
@@ -0,0 +1,71 @@
1
+ import { homedir, platform } from "node:os";
2
+ import { join, win32 } from "node:path";
3
+ function envStr(env, key) {
4
+ const raw = env[key];
5
+ if (raw === undefined)
6
+ return undefined;
7
+ const trimmed = raw.trim();
8
+ return trimmed.length > 0 ? trimmed : undefined;
9
+ }
10
+ /**
11
+ * Canonical fleet root chain (ADR-0005 / superproject ADR-0003 "Resolved decisions"):
12
+ * APIARY_HOME > Linux XDG_STATE_HOME/apiary (only when XDG is explicitly set) > <home>/.apiary.
13
+ * Anchored on `home` (default `os.homedir()`); never reads `process.cwd()`.
14
+ */
15
+ export function resolveFleetRoot(deps = {}) {
16
+ const env = deps.env ?? process.env;
17
+ const home = deps.home ?? homedir();
18
+ const plat = deps.platform ?? platform();
19
+ // Env roots are honored only when ABSOLUTE (fleet security rule, 2026-07-04; the XDG Base
20
+ // Directory spec also requires ignoring relative values). Honoring a relative value would
21
+ // anchor the fleet root (and the registry pidPath derived from it) on process.cwd(), which
22
+ // this resolver must never do. win32.isAbsolute accepts /x, \x, and C:\x, a strict superset
23
+ // of the posix check, so a relative value is never mistaken for absolute on any host.
24
+ const apiaryHome = envStr(env, "APIARY_HOME");
25
+ if (apiaryHome !== undefined && win32.isAbsolute(apiaryHome)) {
26
+ return apiaryHome;
27
+ }
28
+ if (plat === "linux") {
29
+ const xdgStateHome = envStr(env, "XDG_STATE_HOME");
30
+ if (xdgStateHome !== undefined && win32.isAbsolute(xdgStateHome)) {
31
+ return join(xdgStateHome, "apiary");
32
+ }
33
+ }
34
+ return join(home, ".apiary");
35
+ }
36
+ /** Per-product hive state directory: `<fleetRoot>/hive`. */
37
+ export function resolveHiveStateDir(deps = {}) {
38
+ return join(resolveFleetRoot(deps), "hive");
39
+ }
40
+ /** Doctor-owned cross-daemon registry at the fleet root. */
41
+ export function resolveFleetRegistryPath(deps = {}) {
42
+ return join(resolveFleetRoot(deps), "registry.json");
43
+ }
44
+ /** Fleet-root shared install id (doctor/installer-managed; hive read-only). */
45
+ export function resolveSharedInstallIdPath(deps = {}) {
46
+ return join(resolveFleetRoot(deps), "install-id");
47
+ }
48
+ export function resolveHivePidPath(deps = {}) {
49
+ return join(resolveHiveStateDir(deps), "hive.pid");
50
+ }
51
+ export function resolveHiveLockPath(deps = {}) {
52
+ return join(resolveHiveStateDir(deps), "hive.lock");
53
+ }
54
+ export function resolveOnboardingTokenPath(deps = {}) {
55
+ return join(resolveHiveStateDir(deps), "onboarding-token");
56
+ }
57
+ export function resolveStagedWindowsTaskPath(deps = {}) {
58
+ return join(resolveHiveStateDir(deps), "hive-task.xml");
59
+ }
60
+ export function resolveLaunchdLogPaths(deps = {}) {
61
+ const stateDir = resolveHiveStateDir(deps);
62
+ return {
63
+ out: join(stateDir, "launchd.out.log"),
64
+ err: join(stateDir, "launchd.err.log")
65
+ };
66
+ }
67
+ /** Absolute pidPath written into hive's registry entry (ADR Resolved decision 4). */
68
+ export function resolveHiveRegistryPidPath(deps = {}) {
69
+ return resolveHivePidPath(deps);
70
+ }
71
+ //# sourceMappingURL=apiary-root.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiary-root.js","sourceRoot":"","sources":["../../src/shared/apiary-root.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,5 @@ export declare const DOCTOR_STATUS_URL: "http://127.0.0.1:3852/status.json";
10
10
  * server-side relay (`daemon/telemetry-proxy.ts`) can never be pointed at an attacker-chosen origin.
11
11
  */
12
12
  export declare const DOCTOR_EVENTS_URL: "http://127.0.0.1:3852/events";
13
- export declare const HONEYCOMB_HOME_DIR: string;
14
13
  export declare const HIVE_PID_PATH: string;
15
14
  export declare const HIVE_LOCK_PATH: string;
@@ -1,6 +1,5 @@
1
- import { homedir } from "node:os";
2
- import { join } from "node:path";
3
1
  import packageJson from "../../package.json" with { type: "json" };
2
+ import { resolveHiveLockPath, resolveHivePidPath } from "./apiary-root.js";
4
3
  export const HIVE_HOST = "127.0.0.1";
5
4
  export const HIVE_PORT = 3853;
6
5
  export const HIVE_VERSION = packageJson.version;
@@ -13,7 +12,6 @@ export const DOCTOR_STATUS_URL = "http://127.0.0.1:3852/status.json";
13
12
  * server-side relay (`daemon/telemetry-proxy.ts`) can never be pointed at an attacker-chosen origin.
14
13
  */
15
14
  export const DOCTOR_EVENTS_URL = "http://127.0.0.1:3852/events";
16
- export const HONEYCOMB_HOME_DIR = join(homedir(), ".honeycomb");
17
- export const HIVE_PID_PATH = join(HONEYCOMB_HOME_DIR, "hive.pid");
18
- export const HIVE_LOCK_PATH = join(HONEYCOMB_HOME_DIR, "hive.lock");
15
+ export const HIVE_PID_PATH = resolveHivePidPath();
16
+ export const HIVE_LOCK_PATH = resolveHiveLockPath();
19
17
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/shared/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,WAAW,MAAM,oBAAoB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAEnE,MAAM,CAAC,MAAM,SAAS,GAAG,WAAoB,CAAC;AAC9C,MAAM,CAAC,MAAM,SAAS,GAAG,IAAa,CAAC;AACvC,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,CAAC;AAEhD,0GAA0G;AAC1G,MAAM,CAAC,MAAM,iBAAiB,GAAG,mCAA4C,CAAC;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,8BAAuC,CAAC;AAEzE,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AAChE,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC;AAClE,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,EAAE,WAAW,CAAC,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/shared/constants.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,oBAAoB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3E,MAAM,CAAC,MAAM,SAAS,GAAG,WAAoB,CAAC;AAC9C,MAAM,CAAC,MAAM,SAAS,GAAG,IAAa,CAAC;AACvC,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,CAAC;AAEhD,0GAA0G;AAC1G,MAAM,CAAC,MAAM,iBAAiB,GAAG,mCAA4C,CAAC;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,8BAAuC,CAAC;AAEzE,MAAM,CAAC,MAAM,aAAa,GAAG,kBAAkB,EAAE,CAAC;AAClD,MAAM,CAAC,MAAM,cAAc,GAAG,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { FleetRootDeps } from "./apiary-root.js";
2
+ /** Legacy shared runtime dir (pre-fleet-root migration). */
3
+ export declare function resolveLegacyHoneycombHomeDir(deps?: FleetRootDeps): string;
4
+ /** Legacy hive state dir under the shared honeycomb runtime dir. */
5
+ export declare function resolveLegacyHiveStateDir(deps?: FleetRootDeps): string;
6
+ /** Legacy pid/lock lived at the honeycomb home root, not inside the hive subdir. */
7
+ export declare function resolveLegacyHivePidPath(deps?: FleetRootDeps): string;
8
+ export declare function resolveLegacyHiveLockPath(deps?: FleetRootDeps): string;
9
+ /** Legacy doctor registry file (write/read fallback during the compatibility window). */
10
+ export declare function resolveLegacyDoctorRegistryPath(deps?: FleetRootDeps): string;
11
+ /** Legacy shared install-id (read fallback during the compatibility window). */
12
+ export declare function resolveLegacySharedInstallIdPath(deps?: FleetRootDeps): string;
13
+ /** Legacy onboarding token path (read fallback until bootstrap mint moves). */
14
+ export declare function resolveLegacyOnboardingTokenPath(deps?: FleetRootDeps): string;
15
+ /** Module-load defaults (production); prefer the resolvers in tests and injectable call sites. */
16
+ export declare const LEGACY_HONEYCOMB_HOME_DIR: string;
17
+ export declare const LEGACY_HIVE_STATE_DIR: string;
18
+ export declare const LEGACY_HIVE_PID_PATH: string;
19
+ export declare const LEGACY_HIVE_LOCK_PATH: string;
20
+ export declare const LEGACY_DOCTOR_REGISTRY_PATH: string;
21
+ export declare const LEGACY_SHARED_INSTALL_ID_PATH: string;
22
+ export declare const LEGACY_ONBOARDING_TOKEN_PATH: string;
@@ -0,0 +1,48 @@
1
+ import { homedir } from "node:os";
2
+ import { join } from "node:path";
3
+ /**
4
+ * Legacy-window path constants only. Each site carries the fleet ADR removal criterion:
5
+ * delete when every supported install path ships the PRD-010 migration
6
+ * (superproject `library/ledger/EXECUTION_LEDGER-apiary-state-root.md`).
7
+ *
8
+ * Do not use these as runtime defaults; resolve current paths through `apiary-root.ts`.
9
+ */
10
+ function legacyHome(deps = {}) {
11
+ return deps.home ?? homedir();
12
+ }
13
+ /** Legacy shared runtime dir (pre-fleet-root migration). */
14
+ export function resolveLegacyHoneycombHomeDir(deps = {}) {
15
+ return join(legacyHome(deps), ".honeycomb");
16
+ }
17
+ /** Legacy hive state dir under the shared honeycomb runtime dir. */
18
+ export function resolveLegacyHiveStateDir(deps = {}) {
19
+ return join(resolveLegacyHoneycombHomeDir(deps), "hive");
20
+ }
21
+ /** Legacy pid/lock lived at the honeycomb home root, not inside the hive subdir. */
22
+ export function resolveLegacyHivePidPath(deps = {}) {
23
+ return join(resolveLegacyHoneycombHomeDir(deps), "hive.pid");
24
+ }
25
+ export function resolveLegacyHiveLockPath(deps = {}) {
26
+ return join(resolveLegacyHoneycombHomeDir(deps), "hive.lock");
27
+ }
28
+ /** Legacy doctor registry file (write/read fallback during the compatibility window). */
29
+ export function resolveLegacyDoctorRegistryPath(deps = {}) {
30
+ return join(resolveLegacyHoneycombHomeDir(deps), "doctor.daemons.json");
31
+ }
32
+ /** Legacy shared install-id (read fallback during the compatibility window). */
33
+ export function resolveLegacySharedInstallIdPath(deps = {}) {
34
+ return join(resolveLegacyHoneycombHomeDir(deps), "install-id");
35
+ }
36
+ /** Legacy onboarding token path (read fallback until bootstrap mint moves). */
37
+ export function resolveLegacyOnboardingTokenPath(deps = {}) {
38
+ return join(resolveLegacyHiveStateDir(deps), "onboarding-token");
39
+ }
40
+ /** Module-load defaults (production); prefer the resolvers in tests and injectable call sites. */
41
+ export const LEGACY_HONEYCOMB_HOME_DIR = resolveLegacyHoneycombHomeDir();
42
+ export const LEGACY_HIVE_STATE_DIR = resolveLegacyHiveStateDir();
43
+ export const LEGACY_HIVE_PID_PATH = resolveLegacyHivePidPath();
44
+ export const LEGACY_HIVE_LOCK_PATH = resolveLegacyHiveLockPath();
45
+ export const LEGACY_DOCTOR_REGISTRY_PATH = resolveLegacyDoctorRegistryPath();
46
+ export const LEGACY_SHARED_INSTALL_ID_PATH = resolveLegacySharedInstallIdPath();
47
+ export const LEGACY_ONBOARDING_TOKEN_PATH = resolveLegacyOnboardingTokenPath();
48
+ //# sourceMappingURL=legacy-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacy-paths.js","sourceRoot":"","sources":["../../src/shared/legacy-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC;;;;;;GAMG;AAEH,SAAS,UAAU,CAAC,OAAsB,EAAE;IAC1C,OAAO,IAAI,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC;AAChC,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,6BAA6B,CAAC,OAAsB,EAAE;IACpE,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC;AAC9C,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,yBAAyB,CAAC,OAAsB,EAAE;IAChE,OAAO,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;AAC3D,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,wBAAwB,CAAC,OAAsB,EAAE;IAC/D,OAAO,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,OAAsB,EAAE;IAChE,OAAO,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC;AAChE,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,+BAA+B,CAAC,OAAsB,EAAE;IACtE,OAAO,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,EAAE,qBAAqB,CAAC,CAAC;AAC1E,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,gCAAgC,CAAC,OAAsB,EAAE;IACvE,OAAO,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC;AACjE,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,gCAAgC,CAAC,OAAsB,EAAE;IACvE,OAAO,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,EAAE,kBAAkB,CAAC,CAAC;AACnE,CAAC;AAED,kGAAkG;AAClG,MAAM,CAAC,MAAM,yBAAyB,GAAG,6BAA6B,EAAE,CAAC;AACzE,MAAM,CAAC,MAAM,qBAAqB,GAAG,yBAAyB,EAAE,CAAC;AACjE,MAAM,CAAC,MAAM,oBAAoB,GAAG,wBAAwB,EAAE,CAAC;AAC/D,MAAM,CAAC,MAAM,qBAAqB,GAAG,yBAAyB,EAAE,CAAC;AACjE,MAAM,CAAC,MAAM,2BAA2B,GAAG,+BAA+B,EAAE,CAAC;AAC7E,MAAM,CAAC,MAAM,6BAA6B,GAAG,gCAAgC,EAAE,CAAC;AAChF,MAAM,CAAC,MAAM,4BAA4B,GAAG,gCAAgC,EAAE,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { resolveFleetRoot, type FleetRootDeps } from "./apiary-root.js";
2
+ /**
3
+ * Registry compatibility window (ADR-0005 Resolved decision 3):
4
+ * write `<fleetRoot>/registry.json` when the fleet root directory exists, else legacy path; never both.
5
+ */
6
+ export declare function resolveRegistryWritePath(deps?: FleetRootDeps): string;
7
+ export interface ReadRegistryBodyOptions extends FleetRootDeps {
8
+ /** Explicit override for tests (skips the new-then-legacy chain). */
9
+ readonly registryPath?: string;
10
+ readonly readFile?: (path: string) => string;
11
+ }
12
+ /**
13
+ * Read-side fallback chain (rc-AC-4/5/6, mg-AC-10): new path first, then legacy, then absent.
14
+ * The legacy fallback is ABSENCE-triggered only (ENOENT): a new file that exists but cannot be
15
+ * read (EACCES, EISDIR, corruption at the fs layer) yields `null` (callers degrade to defaults),
16
+ * never stale legacy data, because when the new path exists the new file wins.
17
+ */
18
+ export declare function readRegistryBody(options?: ReadRegistryBodyOptions): string | null;
19
+ export { resolveFleetRoot };
@@ -0,0 +1,52 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { resolveFleetRegistryPath, resolveFleetRoot } from "./apiary-root.js";
3
+ import { resolveLegacyDoctorRegistryPath } from "./legacy-paths.js";
4
+ /**
5
+ * Registry compatibility window (ADR-0005 Resolved decision 3):
6
+ * write `<fleetRoot>/registry.json` when the fleet root directory exists, else legacy path; never both.
7
+ */
8
+ export function resolveRegistryWritePath(deps = {}) {
9
+ const fleetRoot = resolveFleetRoot(deps);
10
+ if (existsSync(fleetRoot)) {
11
+ return resolveFleetRegistryPath(deps);
12
+ }
13
+ return resolveLegacyDoctorRegistryPath(deps);
14
+ }
15
+ function isEnoent(error) {
16
+ return error?.code === "ENOENT";
17
+ }
18
+ /**
19
+ * Read-side fallback chain (rc-AC-4/5/6, mg-AC-10): new path first, then legacy, then absent.
20
+ * The legacy fallback is ABSENCE-triggered only (ENOENT): a new file that exists but cannot be
21
+ * read (EACCES, EISDIR, corruption at the fs layer) yields `null` (callers degrade to defaults),
22
+ * never stale legacy data, because when the new path exists the new file wins.
23
+ */
24
+ export function readRegistryBody(options = {}) {
25
+ const readFile = options.readFile ?? ((path) => readFileSync(path, "utf8"));
26
+ if (options.registryPath !== undefined) {
27
+ try {
28
+ return readFile(options.registryPath);
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ }
34
+ const newPath = resolveFleetRegistryPath(options);
35
+ try {
36
+ return readFile(newPath);
37
+ }
38
+ catch (error) {
39
+ // mg-AC-10: a present-but-unreadable new file must NOT surface legacy data.
40
+ if (!isEnoent(error))
41
+ return null;
42
+ // Legacy-window read fallback (new path absent); removal criterion in legacy-paths.ts.
43
+ try {
44
+ return readFile(resolveLegacyDoctorRegistryPath(options));
45
+ }
46
+ catch {
47
+ return null;
48
+ }
49
+ }
50
+ }
51
+ export { resolveFleetRoot };
52
+ //# sourceMappingURL=registry-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-paths.js","sourceRoot":"","sources":["../../src/shared/registry-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EAAE,wBAAwB,EAAE,gBAAgB,EAAsB,MAAM,kBAAkB,CAAC;AAClG,OAAO,EAAE,+BAA+B,EAAE,MAAM,mBAAmB,CAAC;AAEpE;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAAsB,EAAE;IAC/D,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,OAAO,wBAAwB,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,+BAA+B,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC;AAQD,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAQ,KAAsC,EAAE,IAAI,KAAK,QAAQ,CAAC;AACpE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAmC,EAAE;IACpE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAY,EAAU,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAE5F,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QACvC,IAAI,CAAC;YACH,OAAO,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAClD,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,4EAA4E;QAC5E,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAClC,uFAAuF;QACvF,IAAI,CAAC;YACH,OAAO,QAAQ,CAAC,+BAA+B,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { type FleetRootDeps } from "./apiary-root.js";
2
+ export interface MigrateHiveStateResult {
3
+ readonly migratedFiles: readonly string[];
4
+ readonly skippedFiles: readonly string[];
5
+ readonly errors: readonly string[];
6
+ }
7
+ /**
8
+ * One-time, idempotent, additive migration of hive-owned state (PRD-010b).
9
+ * Fail-soft: never throws; legacy originals remain when copy fails (mg-AC-3).
10
+ */
11
+ export declare function migrateHiveState(deps?: FleetRootDeps): MigrateHiveStateResult;
12
+ /** Best-effort ensure the new hive state dir exists with mode 0o700 (mg-AC-4). */
13
+ export declare function ensureHiveStateDir(deps?: FleetRootDeps): void;
@@ -0,0 +1,92 @@
1
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, rmSync } from "node:fs";
2
+ import { resolveHiveStateDir } from "./apiary-root.js";
3
+ import { resolveLegacyHiveStateDir } from "./legacy-paths.js";
4
+ /** Hive-owned state files copied from the legacy state dir (not pid/lock or launchd logs). */
5
+ const MIGRATABLE_STATE_FILENAMES = [
6
+ "install-id",
7
+ "telemetry.json",
8
+ "onboarding-telemetry.json",
9
+ "hive-task.xml",
10
+ "onboarding-token"
11
+ ];
12
+ function filesEqual(a, b) {
13
+ return readFileSync(a).equals(readFileSync(b));
14
+ }
15
+ function copyVerified(source, dest) {
16
+ copyFileSync(source, dest);
17
+ if (!filesEqual(source, dest)) {
18
+ rmSync(dest, { force: true });
19
+ throw new Error(`verify failed after copy: ${dest}`);
20
+ }
21
+ }
22
+ function migrateOneFile(legacyDir, newDir, filename) {
23
+ const source = `${legacyDir}/${filename}`;
24
+ const dest = `${newDir}/${filename}`;
25
+ if (!existsSync(source))
26
+ return "absent";
27
+ if (existsSync(dest))
28
+ return "skipped";
29
+ try {
30
+ copyVerified(source, dest);
31
+ rmSync(source, { force: true });
32
+ return "migrated";
33
+ }
34
+ catch {
35
+ return "error";
36
+ }
37
+ }
38
+ /**
39
+ * One-time, idempotent, additive migration of hive-owned state (PRD-010b).
40
+ * Fail-soft: never throws; legacy originals remain when copy fails (mg-AC-3).
41
+ */
42
+ export function migrateHiveState(deps = {}) {
43
+ const newDir = resolveHiveStateDir(deps);
44
+ const legacyDir = resolveLegacyHiveStateDir(deps);
45
+ const migratedFiles = [];
46
+ const skippedFiles = [];
47
+ const errors = [];
48
+ const legacyStatePresent = existsSync(legacyDir);
49
+ if (!legacyStatePresent) {
50
+ try {
51
+ mkdirSync(newDir, { recursive: true, mode: 0o700 });
52
+ }
53
+ catch {
54
+ // Best effort; lock acquisition will retry mkdir.
55
+ }
56
+ return { migratedFiles, skippedFiles, errors };
57
+ }
58
+ try {
59
+ mkdirSync(newDir, { recursive: true, mode: 0o700 });
60
+ }
61
+ catch (error) {
62
+ errors.push(error instanceof Error ? error.message : "mkdir failed");
63
+ return { migratedFiles, skippedFiles, errors };
64
+ }
65
+ for (const filename of MIGRATABLE_STATE_FILENAMES) {
66
+ const outcome = migrateOneFile(legacyDir, newDir, filename);
67
+ switch (outcome) {
68
+ case "migrated":
69
+ migratedFiles.push(filename);
70
+ break;
71
+ case "skipped":
72
+ skippedFiles.push(filename);
73
+ break;
74
+ case "error":
75
+ errors.push(filename);
76
+ break;
77
+ case "absent":
78
+ break;
79
+ }
80
+ }
81
+ return { migratedFiles, skippedFiles, errors };
82
+ }
83
+ /** Best-effort ensure the new hive state dir exists with mode 0o700 (mg-AC-4). */
84
+ export function ensureHiveStateDir(deps = {}) {
85
+ try {
86
+ mkdirSync(resolveHiveStateDir(deps), { recursive: true, mode: 0o700 });
87
+ }
88
+ catch {
89
+ // Fail-soft; callers that require the dir will surface errors later.
90
+ }
91
+ }
92
+ //# sourceMappingURL=state-migration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-migration.js","sourceRoot":"","sources":["../../src/shared/state-migration.ts"],"names":[],"mappings":"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"}