miravo 0.4.0 → 0.6.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 (161) hide show
  1. package/README.md +1 -1
  2. package/console-dist/assets/activity-DsWeRq4h.js +1 -0
  3. package/console-dist/assets/api-4AqKvsm9.js +1 -0
  4. package/console-dist/assets/arrow-right-Ea_UhTNi.js +1 -0
  5. package/console-dist/assets/arrow-up-down-DFSjzzl2.js +1 -0
  6. package/console-dist/assets/blueprint-card-classes-DBFCDy0M.js +1 -0
  7. package/console-dist/assets/box-C1WaoOMF.js +1 -0
  8. package/console-dist/assets/card-BjeP32PN.js +1 -0
  9. package/console-dist/assets/catalog-BJzyzbLR.js +1 -0
  10. package/console-dist/assets/catalog-DKjEm-c4.js +1 -0
  11. package/console-dist/assets/catalog-template-icons-BrUeHaCY.js +1 -0
  12. package/console-dist/assets/checkbox-DZlJXTE4.js +1 -0
  13. package/console-dist/assets/chunk-OE4NN4TA-CEjpfhS6.js +3 -0
  14. package/console-dist/assets/combobox-BGnuCYxO.js +1 -0
  15. package/console-dist/assets/control-CPhvwx9o.js +1 -0
  16. package/console-dist/assets/control-Cg2up9NA.js +1 -0
  17. package/console-dist/assets/copy-button-WkbNkMcd.js +1 -0
  18. package/console-dist/assets/createLucideIcon-Bwxw859K.js +1 -0
  19. package/console-dist/assets/deploy-tab-JeWDwPoZ.js +1 -0
  20. package/console-dist/assets/dist-BhbDML0a.js +1 -0
  21. package/console-dist/assets/dist-Cy8XTNFT.js +2 -0
  22. package/console-dist/assets/download-DQ6NH16U.js +1 -0
  23. package/console-dist/assets/engine-store-CrLnz692.js +1 -0
  24. package/console-dist/assets/events-CXm29Ok4.js +1 -0
  25. package/console-dist/assets/events-D01IxhnP.js +1 -0
  26. package/console-dist/assets/fleet-CfxbKXt9.js +1 -0
  27. package/console-dist/assets/fleet-lotMGVqe.js +1 -0
  28. package/console-dist/assets/format-kXTonpDJ.js +1 -0
  29. package/console-dist/assets/gauge-Ci8zNZlk.js +1 -0
  30. package/console-dist/assets/get-error-message-3Q5Q-2G5.js +1 -0
  31. package/console-dist/assets/index-CVPKSDvJ.js +12 -0
  32. package/console-dist/assets/index-DJkgDeun.css +2 -0
  33. package/console-dist/assets/input-BWEQFptx.js +1 -0
  34. package/console-dist/assets/instance-detail-C5IVwuh3.js +1 -0
  35. package/console-dist/assets/label-uephX5ZG.js +1 -0
  36. package/console-dist/assets/layers-CUsLQ1fq.js +1 -0
  37. package/console-dist/assets/login-C3RJli0m.js +126 -0
  38. package/console-dist/assets/models-B_UioWQ5.js +1 -0
  39. package/console-dist/assets/models-_IPlPiZ7.js +1 -0
  40. package/console-dist/assets/not-found-B8gAm08S.js +1 -0
  41. package/console-dist/assets/platform-targets-R3T-4eJ7.js +1 -0
  42. package/console-dist/assets/platforms-BWh0BQ3Y.js +1 -0
  43. package/console-dist/assets/platforms-DStNbtVc.js +1 -0
  44. package/console-dist/assets/proxy-CsnYqnPp.js +9 -0
  45. package/console-dist/assets/query-keys-BvtE7BMs.js +1 -0
  46. package/console-dist/assets/radio-CoHegOv5.js +1 -0
  47. package/console-dist/assets/rolldown-runtime-COnpUsM8.js +1 -0
  48. package/console-dist/assets/select-CeO4vP0G.js +1 -0
  49. package/console-dist/assets/select-display-items-CIzY8953.js +1 -0
  50. package/console-dist/assets/server-D9Kfn8fQ.js +1 -0
  51. package/console-dist/assets/shallow-6lGjQhtJ.js +1 -0
  52. package/console-dist/assets/tags-CiXOIHtY.js +4 -0
  53. package/console-dist/assets/tags-FQCXIxrP.js +1 -0
  54. package/console-dist/assets/tooltip-HGLF366Q.js +1 -0
  55. package/console-dist/assets/transition-nav-link-Df4Rk6vV.js +1 -0
  56. package/console-dist/assets/transition-types-CPlGtM8w.js +1 -0
  57. package/console-dist/assets/triangle-alert-adNk_sea.js +1 -0
  58. package/console-dist/assets/use-platform-stream-DGbK1k2L.js +2 -0
  59. package/console-dist/assets/use-transition-navigate-CCpcWXB0.js +2 -0
  60. package/console-dist/assets/validation-Blvud9_O.js +1 -0
  61. package/console-dist/assets/vendor-charts-CAZdaPlq.js +60 -0
  62. package/console-dist/assets/vendor-table-wd8JuMmT.js +4 -0
  63. package/console-dist/assets/vendor-ui-ByahnaY0.js +1 -0
  64. package/console-dist/index.html +70 -2
  65. package/package.json +9 -8
  66. package/src/__tests__/integration/executable-methods-runner.ts +7 -6
  67. package/src/__tests__/integration/executable-methods.integration.ts +214 -122
  68. package/src/__tests__/integration/opcua-concurrent-clients.integration.ts +314 -0
  69. package/src/commands/adapter.ts +180 -7
  70. package/src/commands/apply.test.ts +62 -0
  71. package/src/commands/apply.ts +216 -0
  72. package/src/commands/cleanup.test.ts +34 -0
  73. package/src/commands/cleanup.ts +201 -0
  74. package/src/commands/export.test.ts +51 -0
  75. package/src/commands/export.ts +404 -0
  76. package/src/commands/fork.ts +2 -2
  77. package/src/commands/inject.ts +2 -2
  78. package/src/commands/load.ts +1 -1
  79. package/src/commands/logs.ts +13 -15
  80. package/src/commands/models.test.ts +1 -1
  81. package/src/commands/models.ts +1 -1
  82. package/src/commands/pause.ts +3 -3
  83. package/src/commands/platforms.test.ts +186 -0
  84. package/src/commands/platforms.ts +371 -0
  85. package/src/commands/remove.ts +1 -1
  86. package/src/commands/reset.ts +2 -2
  87. package/src/commands/spawn.ts +2 -2
  88. package/src/commands/speed.ts +2 -2
  89. package/src/commands/start/adapter-config.ts +157 -0
  90. package/src/commands/start/catalog-le-dt.test.ts +50 -0
  91. package/src/commands/start/catalog-le-dt.ts +187 -0
  92. package/src/commands/start/catalog-model-schema.ts +89 -0
  93. package/src/commands/start/catalog-template-detail.ts +54 -0
  94. package/src/commands/start/daemon.ts +255 -0
  95. package/src/commands/start/display.ts +150 -0
  96. package/src/commands/start/engine-setup.ts +247 -0
  97. package/src/commands/start/events.ts +126 -0
  98. package/src/commands/start/index.ts +897 -0
  99. package/src/commands/start/protocol-plans.ts +239 -0
  100. package/src/commands/start/template-loader.ts +197 -0
  101. package/src/commands/start/template-resolver.ts +185 -0
  102. package/src/commands/start/types.ts +73 -0
  103. package/src/commands/start.test.ts +137 -16
  104. package/src/commands/status.ts +1 -1
  105. package/src/commands/stop.ts +19 -8
  106. package/src/commands/templates.test.ts +1 -1
  107. package/src/commands/templates.ts +1 -3
  108. package/src/index.ts +11 -3
  109. package/src/lib/admin-auth.ts +157 -0
  110. package/src/lib/admin-client.test.ts +31 -15
  111. package/src/lib/admin-client.ts +106 -6
  112. package/src/lib/admin-platform-routes.ts +1017 -0
  113. package/src/lib/admin-platform-stream.test.ts +434 -0
  114. package/src/lib/admin-platform-stream.ts +788 -0
  115. package/src/lib/admin-responses.ts +211 -0
  116. package/src/lib/admin-server.test.ts +274 -55
  117. package/src/lib/admin-server.ts +387 -248
  118. package/src/lib/auth-store.ts +87 -0
  119. package/src/lib/daemon-registry.ts +12 -14
  120. package/src/lib/le/le-apply.test.ts +591 -0
  121. package/src/lib/le/le-apply.ts +832 -0
  122. package/src/lib/le/le-auth.ts +89 -0
  123. package/src/lib/le/le-cleanup.test.ts +168 -0
  124. package/src/lib/le/le-cleanup.ts +399 -0
  125. package/src/lib/le/le-cli-helpers.ts +77 -0
  126. package/src/lib/le/le-client.ts +184 -0
  127. package/src/lib/le/le-concurrency.test.ts +157 -0
  128. package/src/lib/le/le-concurrency.ts +78 -0
  129. package/src/lib/le/le-connection-test.ts +42 -0
  130. package/src/lib/le/le-devicehub-properties.test.ts +53 -0
  131. package/src/lib/le/le-devicehub-properties.ts +33 -0
  132. package/src/lib/le/le-devicehub.ts +213 -0
  133. package/src/lib/le/le-digital-twins.ts +285 -0
  134. package/src/lib/le/le-drivers.ts +23 -0
  135. package/src/lib/le/le-endpoint.ts +40 -0
  136. package/src/lib/le/le-environments.test.ts +73 -0
  137. package/src/lib/le/le-environments.ts +156 -0
  138. package/src/lib/le/le-markers.ts +87 -0
  139. package/src/lib/le/le-plan.test.ts +26 -0
  140. package/src/lib/le/le-plan.ts +109 -0
  141. package/src/lib/le/le-platform-operations.test.ts +198 -0
  142. package/src/lib/le/le-platform-operations.ts +340 -0
  143. package/src/lib/le/le-static-model-schema.ts +78 -0
  144. package/src/lib/le/le-static-planner.test.ts +255 -0
  145. package/src/lib/le/le-static-planner.ts +442 -0
  146. package/src/lib/le/le-template-exporter.test.ts +527 -0
  147. package/src/lib/le/le-template-exporter.ts +459 -0
  148. package/src/lib/le/le-value-types.ts +23 -0
  149. package/src/lib/mqtt-client.ts +1 -2
  150. package/src/lib/resolve-simulation.ts +1 -6
  151. package/src/lib/session-store.ts +110 -0
  152. package/src/lib/shutdown.test.ts +184 -2
  153. package/src/lib/shutdown.ts +104 -34
  154. package/src/lib/template-category.ts +3 -3
  155. package/src/lib/template-locator.ts +8 -2
  156. package/src/lib/ws-hub.ts +72 -46
  157. package/src/logger.ts +39 -14
  158. package/src/output.ts +3 -0
  159. package/console-dist/assets/index-C3XMYq26.css +0 -2
  160. package/console-dist/assets/index-hUJSpKtB.js +0 -119
  161. package/src/commands/start.ts +0 -2023
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Credential storage — persists admin password at ~/.miravo/auth.json.
3
+ *
4
+ * Password priority: MIRAVO_ADMIN_PASSWORD env > ~/.miravo/auth.json > default "admin".
5
+ */
6
+
7
+ import { mkdir } from "node:fs/promises";
8
+ import { resolveMiravoHome } from "@miravo/core";
9
+ import type { PersistedCredential } from "@miravo/shared";
10
+ import { PersistedCredentialSchema } from "@miravo/shared";
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // Paths
14
+ // ---------------------------------------------------------------------------
15
+
16
+ function authFilePath(): string {
17
+ return `${resolveMiravoHome()}/auth.json`;
18
+ }
19
+
20
+ // ---------------------------------------------------------------------------
21
+ // Read / Write
22
+ // ---------------------------------------------------------------------------
23
+
24
+ /** Load persisted credential from ~/.miravo/auth.json. Returns null if missing or invalid. */
25
+ export async function loadCredential(): Promise<PersistedCredential | null> {
26
+ const file = Bun.file(authFilePath());
27
+ if (!(await file.exists())) return null;
28
+ try {
29
+ const raw: unknown = await file.json();
30
+ const result = PersistedCredentialSchema.safeParse(raw);
31
+ return result.success ? result.data : null;
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+
37
+ /** Persist credential to ~/.miravo/auth.json with restricted permissions. */
38
+ export async function saveCredential(username: string, passwordHash: string): Promise<void> {
39
+ const filePath = authFilePath();
40
+ const dir = resolveMiravoHome();
41
+ await mkdir(dir, { recursive: true });
42
+ const data: PersistedCredential = { username, passwordHash };
43
+ await Bun.write(filePath, JSON.stringify(data, null, 2), { mode: 0o600 });
44
+ }
45
+
46
+ // ---------------------------------------------------------------------------
47
+ // Password resolution
48
+ // ---------------------------------------------------------------------------
49
+
50
+ interface ResolvedPassword {
51
+ /** Argon2id hash of the effective admin password. */
52
+ readonly passwordHash: string;
53
+ /** True when the effective password is the literal default "admin". */
54
+ readonly isDefault: boolean;
55
+ }
56
+
57
+ /**
58
+ * Resolve the admin password with priority:
59
+ * 1. MIRAVO_ADMIN_PASSWORD env var (plaintext → hashed)
60
+ * 2. ~/.miravo/auth.json (already hashed)
61
+ * 3. Default "admin" (plaintext → hashed)
62
+ */
63
+ export async function resolveAdminPassword(): Promise<ResolvedPassword> {
64
+ // 1. Environment override
65
+ const envPassword = Bun.env["MIRAVO_ADMIN_PASSWORD"];
66
+ if (envPassword && envPassword.trim().length > 0) {
67
+ return {
68
+ passwordHash: await Bun.password.hash(envPassword),
69
+ isDefault: envPassword === "admin",
70
+ };
71
+ }
72
+
73
+ // 2. Persisted credential file
74
+ const credential = await loadCredential();
75
+ if (credential) {
76
+ return {
77
+ passwordHash: credential.passwordHash,
78
+ isDefault: false, // File exists → user changed password at some point
79
+ };
80
+ }
81
+
82
+ // 3. Default
83
+ return {
84
+ passwordHash: await Bun.password.hash("admin"),
85
+ isDefault: true,
86
+ };
87
+ }
@@ -32,10 +32,10 @@ const DaemonRegistryEntrySchema = z.object({
32
32
  runId: z.string().min(1),
33
33
  });
34
34
 
35
- export type DaemonAdapterEntry = z.infer<typeof DaemonAdapterEntrySchema>;
35
+ type DaemonAdapterEntry = z.infer<typeof DaemonAdapterEntrySchema>;
36
36
  export type DaemonRegistryEntry = z.infer<typeof DaemonRegistryEntrySchema>;
37
37
 
38
- export interface EntryIdentityResult {
38
+ interface EntryIdentityResult {
39
39
  readonly status: "dead" | "verified" | "mismatch" | "unreachable";
40
40
  readonly ready: boolean;
41
41
  }
@@ -45,7 +45,7 @@ export interface EntryIdentityResult {
45
45
  // ---------------------------------------------------------------------------
46
46
 
47
47
  /** Returns the path to the daemon registry directory (`~/.miravo/daemon/`). */
48
- export function daemonDir(): string {
48
+ function daemonDir(): string {
49
49
  return `${resolveMiravoHome()}/daemon`;
50
50
  }
51
51
 
@@ -193,7 +193,15 @@ export function isPidAlive(pid: number): boolean {
193
193
  try {
194
194
  process.kill(pid, 0);
195
195
  return true;
196
- } catch {
196
+ } catch (err) {
197
+ if (
198
+ err &&
199
+ typeof err === "object" &&
200
+ "code" in err &&
201
+ (err.code === "EPERM" || err.code === "EACCES")
202
+ ) {
203
+ return true; // process exists but we can't signal it
204
+ }
197
205
  return false;
198
206
  }
199
207
  }
@@ -239,16 +247,6 @@ export async function probeEntryIdentity(entry: DaemonRegistryEntry): Promise<En
239
247
  }
240
248
  }
241
249
 
242
- export async function isEntryAlive(entry: DaemonRegistryEntry): Promise<boolean> {
243
- const identity = await probeEntryIdentity(entry);
244
- return identity.status === "verified" || identity.status === "unreachable";
245
- }
246
-
247
- export async function canSafelySignalEntry(entry: DaemonRegistryEntry): Promise<boolean> {
248
- const identity = await probeEntryIdentity(entry);
249
- return identity.status === "verified";
250
- }
251
-
252
250
  /**
253
251
  * Remove all registry entries whose processes are no longer alive.
254
252
  * Uses full identity verification (PID + runId) to handle PID reuse.