@hivemagnus/magnus-server 0.0.0-stage → 1.0.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.
Files changed (356) hide show
  1. package/.env.example +171 -0
  2. package/LICENSE +202 -0
  3. package/README.md +169 -2
  4. package/agent-version.json +1 -0
  5. package/dist/ai/HEARTBEAT.md +56 -0
  6. package/dist/ai/IDENTITY.md +54 -0
  7. package/dist/ai/MEMORY.md +40 -0
  8. package/dist/ai/TOOLS.md +538 -0
  9. package/dist/ai/USER.md +32 -0
  10. package/dist/cli/args.js +62 -0
  11. package/dist/cli/env-catalog.js +131 -0
  12. package/dist/cli/preflight.js +89 -0
  13. package/dist/cli.js +175 -0
  14. package/dist/config/cors.js +16 -0
  15. package/dist/config/env.js +392 -0
  16. package/dist/config/features.js +16 -0
  17. package/dist/config/index.js +3 -0
  18. package/dist/config/listener-security.js +38 -0
  19. package/dist/config/version.js +31 -0
  20. package/dist/db/client.js +44 -0
  21. package/dist/db/generated/prisma/browser.js +18 -0
  22. package/dist/db/generated/prisma/client.js +35 -0
  23. package/dist/db/generated/prisma/commonInputTypes.js +11 -0
  24. package/dist/db/generated/prisma/enums.js +42 -0
  25. package/dist/db/generated/prisma/internal/class.js +50 -0
  26. package/dist/db/generated/prisma/internal/prismaNamespace.js +1598 -0
  27. package/dist/db/generated/prisma/internal/prismaNamespaceBrowser.js +1569 -0
  28. package/dist/db/generated/prisma/models/A2ATask.js +2 -0
  29. package/dist/db/generated/prisma/models/AdmissionFence.js +2 -0
  30. package/dist/db/generated/prisma/models/Agent.js +2 -0
  31. package/dist/db/generated/prisma/models/AiConversation.js +2 -0
  32. package/dist/db/generated/prisma/models/AiDashboard.js +2 -0
  33. package/dist/db/generated/prisma/models/AiMemory.js +2 -0
  34. package/dist/db/generated/prisma/models/AiMessage.js +2 -0
  35. package/dist/db/generated/prisma/models/AiScheduledOp.js +2 -0
  36. package/dist/db/generated/prisma/models/AlertConditionState.js +2 -0
  37. package/dist/db/generated/prisma/models/AlertRule.js +2 -0
  38. package/dist/db/generated/prisma/models/AlertViolation.js +2 -0
  39. package/dist/db/generated/prisma/models/AnomalyEvent.js +2 -0
  40. package/dist/db/generated/prisma/models/ApplicationObservation.js +2 -0
  41. package/dist/db/generated/prisma/models/ArdentInstallation.js +2 -0
  42. package/dist/db/generated/prisma/models/ArdentProfile.js +2 -0
  43. package/dist/db/generated/prisma/models/ArdentScopeEnrollment.js +2 -0
  44. package/dist/db/generated/prisma/models/CommandResourceFence.js +2 -0
  45. package/dist/db/generated/prisma/models/CommandResourceLease.js +2 -0
  46. package/dist/db/generated/prisma/models/CommandResult.js +2 -0
  47. package/dist/db/generated/prisma/models/CronJob.js +2 -0
  48. package/dist/db/generated/prisma/models/CronJobExecution.js +2 -0
  49. package/dist/db/generated/prisma/models/DeployJob.js +2 -0
  50. package/dist/db/generated/prisma/models/DriftScan.js +2 -0
  51. package/dist/db/generated/prisma/models/EngineeringMetricSample.js +2 -0
  52. package/dist/db/generated/prisma/models/EngineeringRecoveryExercise.js +2 -0
  53. package/dist/db/generated/prisma/models/ExecutionRun.js +2 -0
  54. package/dist/db/generated/prisma/models/FilePatchTask.js +2 -0
  55. package/dist/db/generated/prisma/models/GpuSnapshot.js +2 -0
  56. package/dist/db/generated/prisma/models/HealthSnapshot.js +2 -0
  57. package/dist/db/generated/prisma/models/HermesCoreRollout.js +2 -0
  58. package/dist/db/generated/prisma/models/HermesCoreRolloutHost.js +2 -0
  59. package/dist/db/generated/prisma/models/HermesCredentialPool.js +2 -0
  60. package/dist/db/generated/prisma/models/HermesCredentialPoolAttachment.js +2 -0
  61. package/dist/db/generated/prisma/models/HermesCronJob.js +2 -0
  62. package/dist/db/generated/prisma/models/HermesHook.js +2 -0
  63. package/dist/db/generated/prisma/models/HermesInstallation.js +2 -0
  64. package/dist/db/generated/prisma/models/HermesMcpServer.js +2 -0
  65. package/dist/db/generated/prisma/models/HermesMcpServerAttachment.js +2 -0
  66. package/dist/db/generated/prisma/models/HermesMessagingBinding.js +2 -0
  67. package/dist/db/generated/prisma/models/HermesOperationJob.js +2 -0
  68. package/dist/db/generated/prisma/models/HermesPluginInstall.js +2 -0
  69. package/dist/db/generated/prisma/models/HermesProfile.js +2 -0
  70. package/dist/db/generated/prisma/models/HermesProviderConfig.js +2 -0
  71. package/dist/db/generated/prisma/models/HermesRegistryClient.js +2 -0
  72. package/dist/db/generated/prisma/models/HermesRegistryInventory.js +2 -0
  73. package/dist/db/generated/prisma/models/HermesRegistryReceipt.js +2 -0
  74. package/dist/db/generated/prisma/models/HermesRegistryRevision.js +2 -0
  75. package/dist/db/generated/prisma/models/HermesRegistryTarget.js +2 -0
  76. package/dist/db/generated/prisma/models/HermesRole.js +2 -0
  77. package/dist/db/generated/prisma/models/HermesRoleApplication.js +2 -0
  78. package/dist/db/generated/prisma/models/HermesSkillAssignment.js +2 -0
  79. package/dist/db/generated/prisma/models/HermesToolsetPolicy.js +2 -0
  80. package/dist/db/generated/prisma/models/IncidentLesson.js +2 -0
  81. package/dist/db/generated/prisma/models/LibraryCategory.js +2 -0
  82. package/dist/db/generated/prisma/models/LibraryFile.js +2 -0
  83. package/dist/db/generated/prisma/models/LogEntry.js +2 -0
  84. package/dist/db/generated/prisma/models/MagnusReleaseCanary.js +2 -0
  85. package/dist/db/generated/prisma/models/MaintenanceWindow.js +2 -0
  86. package/dist/db/generated/prisma/models/ManagedCronDefinition.js +2 -0
  87. package/dist/db/generated/prisma/models/ManagedCronOccurrence.js +2 -0
  88. package/dist/db/generated/prisma/models/Node.js +2 -0
  89. package/dist/db/generated/prisma/models/Notification.js +2 -0
  90. package/dist/db/generated/prisma/models/NotificationPreference.js +2 -0
  91. package/dist/db/generated/prisma/models/RemediationExecution.js +2 -0
  92. package/dist/db/generated/prisma/models/RemediationRule.js +2 -0
  93. package/dist/db/generated/prisma/models/RemoteCommand.js +2 -0
  94. package/dist/db/generated/prisma/models/ResourceDrainParticipant.js +2 -0
  95. package/dist/db/generated/prisma/models/ResourceEnrollment.js +2 -0
  96. package/dist/db/generated/prisma/models/ResourceParticipantWork.js +2 -0
  97. package/dist/db/generated/prisma/models/Role.js +2 -0
  98. package/dist/db/generated/prisma/models/RoleApplication.js +2 -0
  99. package/dist/db/generated/prisma/models/RolloutTarget.js +2 -0
  100. package/dist/db/generated/prisma/models/SecurityExportOutbox.js +2 -0
  101. package/dist/db/generated/prisma/models/SecurityFusionAction.js +2 -0
  102. package/dist/db/generated/prisma/models/SecurityFusionActionApproval.js +2 -0
  103. package/dist/db/generated/prisma/models/SecurityFusionCase.js +2 -0
  104. package/dist/db/generated/prisma/models/SecurityFusionCaseActivity.js +2 -0
  105. package/dist/db/generated/prisma/models/SecurityFusionCaseEntity.js +2 -0
  106. package/dist/db/generated/prisma/models/SecurityFusionCaseEvent.js +2 -0
  107. package/dist/db/generated/prisma/models/SecurityFusionCaseRelationship.js +2 -0
  108. package/dist/db/generated/prisma/models/SecurityFusionCollector.js +2 -0
  109. package/dist/db/generated/prisma/models/SecurityFusionCommandOutbox.js +2 -0
  110. package/dist/db/generated/prisma/models/SecurityFusionDeletionReceipt.js +2 -0
  111. package/dist/db/generated/prisma/models/SecurityFusionDelivery.js +2 -0
  112. package/dist/db/generated/prisma/models/SecurityFusionEntity.js +2 -0
  113. package/dist/db/generated/prisma/models/SecurityFusionEntityAlias.js +2 -0
  114. package/dist/db/generated/prisma/models/SecurityFusionEvent.js +2 -0
  115. package/dist/db/generated/prisma/models/SecurityFusionEventEntity.js +2 -0
  116. package/dist/db/generated/prisma/models/SecurityFusionEvidence.js +2 -0
  117. package/dist/db/generated/prisma/models/SecurityFusionInvestigation.js +2 -0
  118. package/dist/db/generated/prisma/models/SecurityFusionNonce.js +2 -0
  119. package/dist/db/generated/prisma/models/SecurityFusionReceiptChainHead.js +2 -0
  120. package/dist/db/generated/prisma/models/SecurityFusionRuleVersion.js +2 -0
  121. package/dist/db/generated/prisma/models/SecurityFusionSourceState.js +2 -0
  122. package/dist/db/generated/prisma/models/SecurityServiceState.js +2 -0
  123. package/dist/db/generated/prisma/models/SharedResourceFence.js +2 -0
  124. package/dist/db/generated/prisma/models/SharedResourceLease.js +2 -0
  125. package/dist/db/generated/prisma/models/SharedResourceLeaseResource.js +2 -0
  126. package/dist/db/generated/prisma/models/SkillInstallation.js +2 -0
  127. package/dist/db/generated/prisma/models/SkillRegistryEntry.js +2 -0
  128. package/dist/db/generated/prisma/models/SkillTag.js +2 -0
  129. package/dist/db/generated/prisma/models/SkillVersion.js +2 -0
  130. package/dist/db/generated/prisma/models/TeamApprovalDecision.js +2 -0
  131. package/dist/db/generated/prisma/models/User.js +2 -0
  132. package/dist/db/generated/prisma/models/WebhookDelivery.js +2 -0
  133. package/dist/db/generated/prisma/models/WebhookEndpoint.js +2 -0
  134. package/dist/db/generated/prisma/models.js +2 -0
  135. package/dist/db/index.js +3 -0
  136. package/dist/db/read-retry.js +35 -0
  137. package/dist/db/seed.js +348 -0
  138. package/dist/index.js +162 -0
  139. package/dist/middleware/auth.js +361 -0
  140. package/dist/middleware/body-limit.js +14 -0
  141. package/dist/middleware/correlation-id.js +13 -0
  142. package/dist/middleware/error-handler.js +28 -0
  143. package/dist/middleware/iam-token.js +21 -0
  144. package/dist/middleware/rate-limit.js +78 -0
  145. package/dist/middleware/request-logger.js +85 -0
  146. package/dist/middleware/security-headers.js +23 -0
  147. package/dist/middleware/tracing.js +120 -0
  148. package/dist/middleware/user-status.js +33 -0
  149. package/dist/openapi/spec.js +2656 -0
  150. package/dist/queue/redis.js +20 -0
  151. package/dist/queue/requeue.js +27 -0
  152. package/dist/queue/workers.js +342 -0
  153. package/dist/routes/ai-schedule.js +73 -0
  154. package/dist/routes/alerts.js +79 -0
  155. package/dist/routes/anomalies.js +101 -0
  156. package/dist/routes/ardent.js +82 -0
  157. package/dist/routes/assistant.js +417 -0
  158. package/dist/routes/audit.js +138 -0
  159. package/dist/routes/codex.js +65 -0
  160. package/dist/routes/commands.js +226 -0
  161. package/dist/routes/credentials.js +58 -0
  162. package/dist/routes/cron.js +292 -0
  163. package/dist/routes/dependencies.js +49 -0
  164. package/dist/routes/deploy.js +18 -0
  165. package/dist/routes/discovery.js +168 -0
  166. package/dist/routes/docs.js +24 -0
  167. package/dist/routes/drift.js +126 -0
  168. package/dist/routes/events-stream.js +87 -0
  169. package/dist/routes/files.js +214 -0
  170. package/dist/routes/fleet-checks.js +21 -0
  171. package/dist/routes/health.js +133 -0
  172. package/dist/routes/heartbeat.js +545 -0
  173. package/dist/routes/hermes-registry.js +278 -0
  174. package/dist/routes/hermes.js +61 -0
  175. package/dist/routes/library.js +402 -0
  176. package/dist/routes/logs.js +172 -0
  177. package/dist/routes/managed-cron.js +23 -0
  178. package/dist/routes/mcp.js +39 -0
  179. package/dist/routes/metrics.js +187 -0
  180. package/dist/routes/nodes.js +951 -0
  181. package/dist/routes/notifications.js +130 -0
  182. package/dist/routes/ops.js +258 -0
  183. package/dist/routes/orchestra.js +430 -0
  184. package/dist/routes/predictions.js +23 -0
  185. package/dist/routes/profiling.js +68 -0
  186. package/dist/routes/quick-command.js +72 -0
  187. package/dist/routes/remediation.js +111 -0
  188. package/dist/routes/resource-leases.js +297 -0
  189. package/dist/routes/roles.js +370 -0
  190. package/dist/routes/rollout.js +124 -0
  191. package/dist/routes/scan.js +116 -0
  192. package/dist/routes/security-backup.js +58 -0
  193. package/dist/routes/security-fusion.js +605 -0
  194. package/dist/routes/security-integration.js +71 -0
  195. package/dist/routes/self-update.js +129 -0
  196. package/dist/routes/shared-resource-leases.js +78 -0
  197. package/dist/routes/skills.js +485 -0
  198. package/dist/routes/stats.js +96 -0
  199. package/dist/routes/team-approvals.js +23 -0
  200. package/dist/routes/terminal-ticket.js +15 -0
  201. package/dist/routes/terminal.js +17 -0
  202. package/dist/routes/topology.js +37 -0
  203. package/dist/routes/users.js +219 -0
  204. package/dist/routes/webhooks.js +137 -0
  205. package/dist/schemas/command-reconciliation.js +14 -0
  206. package/dist/schemas/commands.js +51 -0
  207. package/dist/schemas/cron.js +33 -0
  208. package/dist/schemas/deploy.js +20 -0
  209. package/dist/schemas/files.js +14 -0
  210. package/dist/schemas/hermes.js +69 -0
  211. package/dist/schemas/index.js +11 -0
  212. package/dist/schemas/library.js +48 -0
  213. package/dist/schemas/logs.js +35 -0
  214. package/dist/schemas/managed-cron.js +127 -0
  215. package/dist/schemas/node-responses.js +87 -0
  216. package/dist/schemas/node-session-receipt.js +84 -0
  217. package/dist/schemas/nodes.js +36 -0
  218. package/dist/schemas/orchestra.js +118 -0
  219. package/dist/schemas/resource-participant-reconciliation.js +99 -0
  220. package/dist/schemas/roles.js +54 -0
  221. package/dist/schemas/shared-resource-lease.js +132 -0
  222. package/dist/schemas/skills.js +44 -0
  223. package/dist/schemas/users.js +28 -0
  224. package/dist/scripts/run-disposable-recovery-exercise.js +39 -0
  225. package/dist/sdk/index.js +2 -0
  226. package/dist/sdk/node-api-client.js +474 -0
  227. package/dist/security/approval-assertion.js +66 -0
  228. package/dist/security/command-completion-registry.js +35 -0
  229. package/dist/security/command-request.js +12 -0
  230. package/dist/security/command-result-signature.js +34 -0
  231. package/dist/security/managed-http.js +45 -0
  232. package/dist/security/native-completion-registry.js +44 -0
  233. package/dist/server.js +178 -0
  234. package/dist/services/admission-fence.js +71 -0
  235. package/dist/services/ai-assistant-service.js +2523 -0
  236. package/dist/services/ai-correlation-service.js +225 -0
  237. package/dist/services/ai-export-service.js +141 -0
  238. package/dist/services/ai-insights-service.js +219 -0
  239. package/dist/services/ai-schedule-service.js +145 -0
  240. package/dist/services/ai-scratchpad-service.js +222 -0
  241. package/dist/services/ai-tools.js +1343 -0
  242. package/dist/services/alert-service.js +313 -0
  243. package/dist/services/anomaly-detector.js +419 -0
  244. package/dist/services/api-local-work.js +79 -0
  245. package/dist/services/application-probes.js +309 -0
  246. package/dist/services/ardent-scope-enrollment.js +123 -0
  247. package/dist/services/ardent-service.js +86 -0
  248. package/dist/services/audit-service.js +308 -0
  249. package/dist/services/codex-service.js +209 -0
  250. package/dist/services/command-lifecycle.js +60 -0
  251. package/dist/services/command-resource-leases.js +305 -0
  252. package/dist/services/control-host-node.js +242 -0
  253. package/dist/services/credential-rotation-service.js +294 -0
  254. package/dist/services/dependency-service.js +145 -0
  255. package/dist/services/disposable-recovery-runner.js +595 -0
  256. package/dist/services/docker-group-health.js +121 -0
  257. package/dist/services/engineering-assurance.js +492 -0
  258. package/dist/services/engineering-evidence-ledger.js +94 -0
  259. package/dist/services/engineering-metric-evidence.js +26 -0
  260. package/dist/services/event-bus.js +227 -0
  261. package/dist/services/fleet-check-log.js +102 -0
  262. package/dist/services/forecast-service.js +154 -0
  263. package/dist/services/health-retention.js +175 -0
  264. package/dist/services/heartbeat-stream.js +63 -0
  265. package/dist/services/hermes-catalog-import.js +62 -0
  266. package/dist/services/hermes-cli-parser.js +671 -0
  267. package/dist/services/hermes-core-rollout.js +90 -0
  268. package/dist/services/hermes-dashboard-endpoint.js +13 -0
  269. package/dist/services/hermes-plugin-source.js +149 -0
  270. package/dist/services/hermes-registry-service.js +258 -0
  271. package/dist/services/hermes-service.js +566 -0
  272. package/dist/services/hivemem-client.js +85 -0
  273. package/dist/services/host-local-writer.js +82 -0
  274. package/dist/services/incident-evidence.js +110 -0
  275. package/dist/services/incident-lessons.js +186 -0
  276. package/dist/services/llm-providers/anthropic.js +143 -0
  277. package/dist/services/llm-providers/index.js +7 -0
  278. package/dist/services/llm-providers/llama-cpp.js +237 -0
  279. package/dist/services/llm-providers/ollama.js +292 -0
  280. package/dist/services/llm-providers/openai-compatible.js +200 -0
  281. package/dist/services/llm-providers/provider-error.js +36 -0
  282. package/dist/services/llm-providers/registry.js +45 -0
  283. package/dist/services/llm-providers/types.js +2 -0
  284. package/dist/services/log-emitter.js +19 -0
  285. package/dist/services/log-retention.js +66 -0
  286. package/dist/services/maintenance-service.js +29 -0
  287. package/dist/services/managed-cron.js +493 -0
  288. package/dist/services/managed-ssh-admission.js +68 -0
  289. package/dist/services/monitor-pulse.js +10 -0
  290. package/dist/services/node-issue-monitor.js +71 -0
  291. package/dist/services/node-service.js +35 -0
  292. package/dist/services/notification-retention.js +51 -0
  293. package/dist/services/notification-service.js +94 -0
  294. package/dist/services/operational-observations.js +112 -0
  295. package/dist/services/operations-config.js +67 -0
  296. package/dist/services/ops-service.js +491 -0
  297. package/dist/services/orchestra-extras-service.js +370 -0
  298. package/dist/services/orchestra-resources-service.js +530 -0
  299. package/dist/services/os-scheduler-writer.js +73 -0
  300. package/dist/services/password-service.js +22 -0
  301. package/dist/services/prediction-service.js +284 -0
  302. package/dist/services/recovery-exercises.js +682 -0
  303. package/dist/services/remediation-service.js +325 -0
  304. package/dist/services/resource-enrollment.js +433 -0
  305. package/dist/services/resource-node-lock.js +18 -0
  306. package/dist/services/resource-participant-work.js +302 -0
  307. package/dist/services/role-service.js +388 -0
  308. package/dist/services/rollout-service.js +440 -0
  309. package/dist/services/security-export.js +185 -0
  310. package/dist/services/security-fusion-actions.js +22 -0
  311. package/dist/services/security-fusion-approvals.js +83 -0
  312. package/dist/services/security-fusion-evidence-integrity.js +144 -0
  313. package/dist/services/security-fusion-ingest.js +101 -0
  314. package/dist/services/security-fusion-outbox.js +185 -0
  315. package/dist/services/security-fusion-receipt-chain.js +134 -0
  316. package/dist/services/security-fusion-service.js +751 -0
  317. package/dist/services/security-fusion-verification.js +50 -0
  318. package/dist/services/self-update-service.js +200 -0
  319. package/dist/services/shared-resource-leases.js +413 -0
  320. package/dist/services/skill-publication-bundle.js +90 -0
  321. package/dist/services/skill-publication-settlement.js +36 -0
  322. package/dist/services/skill-publication-state.js +40 -0
  323. package/dist/services/skill-registry-service.js +327 -0
  324. package/dist/services/skill-service.js +148 -0
  325. package/dist/services/ssh-exec-service.js +139 -0
  326. package/dist/services/ssh-host-verification.js +27 -0
  327. package/dist/services/tailscale-node-key-service.js +75 -0
  328. package/dist/services/team-approvals.js +118 -0
  329. package/dist/services/topology-service.js +138 -0
  330. package/dist/services/transfer-authority-snapshot.js +151 -0
  331. package/dist/services/webhook-credential-migration.js +97 -0
  332. package/dist/services/webhook-security.js +242 -0
  333. package/dist/services/webhook-service.js +494 -0
  334. package/dist/types/auth.js +3 -0
  335. package/dist/types/index.js +3 -0
  336. package/dist/types/library.js +3 -0
  337. package/dist/types/notifications.js +3 -0
  338. package/dist/types/roles.js +3 -0
  339. package/dist/types/shared-contracts.js +3 -0
  340. package/dist/utils/env.js +141 -0
  341. package/dist/utils/heartbeat-peer.js +19 -0
  342. package/dist/utils/idempotency.js +45 -0
  343. package/dist/utils/ip.js +25 -0
  344. package/dist/utils/json-fields.js +94 -0
  345. package/dist/utils/local-tls.js +39 -0
  346. package/dist/utils/magnus-home.js +15 -0
  347. package/dist/utils/node-url.js +59 -0
  348. package/dist/utils/redact.js +26 -0
  349. package/dist/utils/safe-equal.js +13 -0
  350. package/dist/utils/sentinel-nodes.js +16 -0
  351. package/dist/utils/validate.js +41 -0
  352. package/package.json +119 -4
  353. package/prisma/migrations/20261031000000_baseline/migration.sql +2935 -0
  354. package/prisma/migrations/migration_lock.toml +3 -0
  355. package/prisma/schema.prisma +2185 -0
  356. package/prisma.config.ts +14 -0
@@ -0,0 +1,348 @@
1
+ /**
2
+ * Base data every installation needs: the internal system actor (never a
3
+ * login-capable administrator), the sentinel nodes that internal log sources
4
+ * reference, and the starter library. Safe to run repeatedly; `magnus-server
5
+ * migrate` runs it after applying migrations.
6
+ */
7
+ import { randomBytes } from 'node:crypto';
8
+ import argon2 from 'argon2';
9
+ /** Argon2id config per project security conventions. */
10
+ const ARGON2_OPTIONS = {
11
+ type: argon2.argon2id,
12
+ memoryCost: 65536,
13
+ timeCost: 3,
14
+ parallelism: 4,
15
+ };
16
+ async function hashPassword(password) {
17
+ return argon2.hash(password, ARGON2_OPTIONS);
18
+ }
19
+ /** Idempotently create the system actor, sentinel nodes and library content. */
20
+ export async function seedDatabase(prisma, log = console.log) {
21
+ log('🌱 Seeding database…');
22
+ // ── System user (used by API-secret / agent auth) ──
23
+ let systemUser = await prisma.user.findUnique({ where: { id: 'system' } });
24
+ if (!systemUser) {
25
+ systemUser = await prisma.user.findUnique({ where: { email: 'system@magnus.local' } });
26
+ }
27
+ if (!systemUser) {
28
+ systemUser = await prisma.user.create({
29
+ data: {
30
+ id: 'system',
31
+ email: 'system@magnus.local',
32
+ name: 'System',
33
+ password: await hashPassword(randomBytes(32).toString('hex')),
34
+ role: 'ADMIN',
35
+ active: true,
36
+ },
37
+ });
38
+ }
39
+ log(` āœ“ User: ${systemUser.email} (${systemUser.role}) [system actor]`);
40
+ // ── Sentinel nodes for internal log sources ──
41
+ // These virtual nodes allow Control API and Dashboard logs to use the
42
+ // same logEntry table with referential integrity intact.
43
+ const sentinelNodes = [
44
+ {
45
+ id: '__control-api__',
46
+ name: '__control-api__',
47
+ hostname: '__control-api__',
48
+ ipAddress: '127.0.0.1',
49
+ port: 4000,
50
+ os: 'internal',
51
+ arch: 'internal',
52
+ token: `sentinel-control-api-${randomBytes(16).toString('hex')}`,
53
+ },
54
+ {
55
+ id: '__dashboard__',
56
+ name: '__dashboard__',
57
+ hostname: '__dashboard__',
58
+ ipAddress: '127.0.0.1',
59
+ port: 3000,
60
+ os: 'internal',
61
+ arch: 'internal',
62
+ token: `sentinel-dashboard-${randomBytes(16).toString('hex')}`,
63
+ },
64
+ ];
65
+ for (const sentinel of sentinelNodes) {
66
+ const existing = await prisma.node.findUnique({ where: { id: sentinel.id } });
67
+ if (!existing) {
68
+ await prisma.node.create({
69
+ data: {
70
+ id: sentinel.id,
71
+ name: sentinel.name,
72
+ hostname: sentinel.hostname,
73
+ ipAddress: sentinel.ipAddress,
74
+ port: sentinel.port,
75
+ status: 'ONLINE',
76
+ os: sentinel.os,
77
+ arch: sentinel.arch,
78
+ token: sentinel.token,
79
+ metadata: '{"sentinel":true}',
80
+ },
81
+ });
82
+ log(` āœ“ Sentinel Node: ${sentinel.name}`);
83
+ }
84
+ else {
85
+ log(` āœ“ Sentinel Node: ${sentinel.name} (already exists)`);
86
+ }
87
+ }
88
+ // ── Library: Categories ──
89
+ const personalityCat = await prisma.libraryCategory.upsert({
90
+ where: { name: 'Personality' },
91
+ update: {},
92
+ create: {
93
+ name: 'Personality',
94
+ description: 'Core identity and personality files for Orchestra agents',
95
+ color: '#6366f1',
96
+ sortOrder: 0,
97
+ },
98
+ });
99
+ log(` āœ“ Library Category: ${personalityCat.name}`);
100
+ const knowledgeCat = await prisma.libraryCategory.upsert({
101
+ where: { name: 'Knowledge' },
102
+ update: {},
103
+ create: {
104
+ name: 'Knowledge',
105
+ description: 'Knowledge bases and reference material',
106
+ color: '#3b82f6',
107
+ sortOrder: 1,
108
+ },
109
+ });
110
+ log(` āœ“ Library Category: ${knowledgeCat.name}`);
111
+ const templatesCat = await prisma.libraryCategory.upsert({
112
+ where: { name: 'Templates' },
113
+ update: {},
114
+ create: {
115
+ name: 'Templates',
116
+ description: 'Reusable file templates and boilerplates',
117
+ color: '#22c55e',
118
+ sortOrder: 2,
119
+ },
120
+ });
121
+ log(` āœ“ Library Category: ${templatesCat.name}`);
122
+ const configCat = await prisma.libraryCategory.upsert({
123
+ where: { name: 'Config' },
124
+ update: {},
125
+ create: {
126
+ name: 'Config',
127
+ description: 'Configuration files and system settings',
128
+ color: '#f59e0b',
129
+ sortOrder: 3,
130
+ },
131
+ });
132
+ log(` āœ“ Library Category: ${configCat.name}`);
133
+ // ── Library: Standard Agent Files ──
134
+ const agentFiles = [
135
+ {
136
+ name: 'SOUL',
137
+ fileName: 'SOUL.md',
138
+ mimeType: 'text/markdown',
139
+ categoryId: personalityCat.id,
140
+ tags: '["personality","core","identity"]',
141
+ content: `# SOUL.md — Agent Personality Definition
142
+
143
+ ## Identity
144
+ You are a Magnus fleet node agent — a helpful, precise, and security-conscious AI assistant that manages Linux systems.
145
+
146
+ ## Core Traits
147
+ - **Reliable**: Always follow through on tasks and provide accurate status updates
148
+ - **Security-First**: Never expose secrets, tokens, or sensitive data in logs or responses
149
+ - **Transparent**: Explain what you're doing and why before executing commands
150
+ - **Cautious**: Warn about destructive operations and request confirmation
151
+ - **Efficient**: Minimize resource usage and prefer lightweight solutions
152
+
153
+ ## Communication Style
154
+ - Clear, concise responses without unnecessary verbosity
155
+ - Technical accuracy with appropriate detail level
156
+ - Use markdown formatting for structured output
157
+ - Include relevant context without overwhelming the operator
158
+
159
+ ## Boundaries
160
+ - Never modify system files without explicit authorization
161
+ - Always validate inputs before executing commands
162
+ - Respect resource limits and timeout constraints
163
+ - Escalate unknown situations rather than guessing
164
+ `,
165
+ },
166
+ {
167
+ name: 'MEMORY',
168
+ fileName: 'MEMORY.md',
169
+ mimeType: 'text/markdown',
170
+ categoryId: personalityCat.id,
171
+ tags: '["memory","context","state"]',
172
+ content: `# MEMORY.md — Agent Memory & Context
173
+
174
+ ## Operational Context
175
+ - Managed by Magnus Fleet Management Platform
176
+ - Reports to control-api via heartbeat every 30 seconds
177
+ - Executes commands dispatched through BullMQ queue
178
+
179
+ ## Known Facts
180
+ - Operating system details are collected via HealthCollector
181
+ - Disk, CPU, memory, and network stats are monitored continuously
182
+ - Cron jobs are managed with MAGNUS: markers in system crontab
183
+
184
+ ## Session History
185
+ <!-- This file is updated as the agent learns and remembers -->
186
+ - Initial deployment: Agent installed and registered with control plane
187
+ - Health monitoring: Active and reporting nominal metrics
188
+
189
+ ## Important Notes
190
+ - File sync operations require checksum verification
191
+ - Skill installations go to /opt/magnus/skills/
192
+ - Self-updates require systemd restart scheduling
193
+ `,
194
+ },
195
+ {
196
+ name: 'KNOWLEDGE',
197
+ fileName: 'KNOWLEDGE.md',
198
+ mimeType: 'text/markdown',
199
+ categoryId: knowledgeCat.id,
200
+ tags: '["knowledge","reference","docs"]',
201
+ content: `# KNOWLEDGE.md — Agent Knowledge Base
202
+
203
+ ## System Administration
204
+ - Package management: apt/dnf depending on distro
205
+ - Service management: systemctl for systemd services
206
+ - Log management: journalctl for system logs
207
+ - Network: ip, ss, netstat for network diagnostics
208
+ - Disk: df, du, lsblk for storage management
209
+
210
+ ## Magnus Platform
211
+ - Control API runs on port 4000
212
+ - Node Manager agents run on port 4100
213
+ - Dashboard available on port 3000
214
+ - Redis on port 6379 for queues and caching
215
+
216
+ ## Security Practices
217
+ - Tokens are JWT-signed with HS256
218
+ - Node authentication via x-node-token header
219
+ - All state changes are audit-logged
220
+ - Secrets are never logged or returned in API responses
221
+
222
+ ## Common Tasks
223
+ - Health check: GET /health
224
+ - Command execution: POST /execute with timeout
225
+ - File sync: POST /files/update with checksum
226
+ - Cron management: POST /cron with MAGNUS markers
227
+ `,
228
+ },
229
+ {
230
+ name: 'SKILLS',
231
+ fileName: 'SKILLS.md',
232
+ mimeType: 'text/markdown',
233
+ categoryId: knowledgeCat.id,
234
+ tags: '["skills","capabilities","reference"]',
235
+ content: `# SKILLS.md — Agent Capabilities
236
+
237
+ ## Core Skills
238
+ 1. **System Monitoring** — Collect and report CPU, memory, disk, network metrics
239
+ 2. **Command Execution** — Run shell commands with timeout and output capture
240
+ 3. **Cron Management** — Create, update, delete cron jobs with tracking markers
241
+ 4. **File Sync** — Read and write files with checksum verification
242
+ 5. **Skill Installation** — Download, verify, and install skill bundles
243
+ 6. **Self-Update** — Download new agent version and schedule restart
244
+
245
+ ## Monitoring Capabilities
246
+ - CPU usage percentage and load averages
247
+ - Memory and swap utilization
248
+ - Disk usage per mount point
249
+ - Network interface statistics
250
+ - Service status via systemctl
251
+ - Cockpit availability detection
252
+
253
+ ## Execution Constraints
254
+ - Maximum command timeout: configurable (default 300s)
255
+ - Output size limit: 1MB per command
256
+ - Concurrent executions: limited by BullMQ concurrency
257
+ - Risk assessment: low/medium/high classification
258
+ `,
259
+ },
260
+ {
261
+ name: 'RULES',
262
+ fileName: 'RULES.md',
263
+ mimeType: 'text/markdown',
264
+ categoryId: personalityCat.id,
265
+ tags: '["rules","constraints","safety"]',
266
+ content: `# RULES.md — Agent Operating Rules
267
+
268
+ ## Critical Rules (Never Violate)
269
+ 1. **Never expose secrets** — tokens, passwords, API keys must never appear in logs or responses
270
+ 2. **Never execute without authorization** — all commands must come through the authenticated control plane
271
+ 3. **Always verify checksums** — file sync and skill installations must verify integrity
272
+ 4. **Respect timeouts** — kill processes that exceed their timeout limit
273
+ 5. **Audit everything** — all state-changing operations must be logged
274
+
275
+ ## Operational Rules
276
+ 1. Report health status every 30 seconds via heartbeat
277
+ 2. Update agent status when starting/stopping operations
278
+ 3. Use idempotency keys to prevent duplicate command execution
279
+ 4. Preserve existing cron jobs that don't have MAGNUS markers
280
+ 5. Back up files before overwriting when previousChecksum exists
281
+
282
+ ## Safety Rules
283
+ 1. Warn before executing destructive commands (rm -rf, format, etc.)
284
+ 2. Validate file paths to prevent directory traversal attacks
285
+ 3. Sanitize command output to strip potential secrets
286
+ 4. Limit resource consumption (CPU, memory, disk I/O)
287
+ 5. Gracefully handle network failures with retry logic
288
+ `,
289
+ },
290
+ {
291
+ name: 'GOALS',
292
+ fileName: 'GOALS.md',
293
+ mimeType: 'text/markdown',
294
+ categoryId: personalityCat.id,
295
+ tags: '["goals","objectives","mission"]',
296
+ content: `# GOALS.md — Agent Objectives
297
+
298
+ ## Primary Mission
299
+ Maintain the health, security, and operational readiness of the assigned Linux system as part of the Magnus fleet.
300
+
301
+ ## Ongoing Goals
302
+ 1. **Uptime** — Maximize system availability and minimize unplanned downtime
303
+ 2. **Security** — Keep the system patched, monitored, and free of vulnerabilities
304
+ 3. **Performance** — Optimize resource utilization and identify bottlenecks
305
+ 4. **Compliance** — Ensure all operations follow the rules defined in RULES.md
306
+ 5. **Reporting** — Provide accurate, timely health and status information
307
+
308
+ ## Success Metrics
309
+ - Heartbeat consistency: >99.9% on-time delivery
310
+ - Command execution: <5s average response time
311
+ - Health monitoring: No gaps in metric collection
312
+ - File sync: 100% checksum verification pass rate
313
+ - Skill installations: Zero failed deployments
314
+
315
+ ## Growth Objectives
316
+ - Learn from operational patterns to improve efficiency
317
+ - Adapt to new skill bundles and capabilities
318
+ - Provide proactive alerts and recommendations
319
+ `,
320
+ },
321
+ ];
322
+ for (const file of agentFiles) {
323
+ const existing = await prisma.libraryFile.findFirst({
324
+ where: { fileName: file.fileName },
325
+ });
326
+ if (!existing) {
327
+ await prisma.libraryFile.create({
328
+ data: {
329
+ name: file.name,
330
+ fileName: file.fileName,
331
+ mimeType: file.mimeType,
332
+ content: file.content,
333
+ sizeBytes: Buffer.byteLength(file.content, 'utf-8'),
334
+ categoryId: file.categoryId,
335
+ tags: file.tags,
336
+ createdBy: systemUser.id,
337
+ },
338
+ });
339
+ log(` āœ“ Library File: ${file.fileName}`);
340
+ }
341
+ else {
342
+ log(` āœ“ Library File: ${file.fileName} (already exists)`);
343
+ }
344
+ }
345
+ // ── Skills are now file-based (see skills/ directory) — no DB seeding needed ──
346
+ log('āœ… Seed complete.');
347
+ }
348
+ //# sourceMappingURL=seed.js.map
package/dist/index.js ADDED
@@ -0,0 +1,162 @@
1
+ import { config } from 'dotenv';
2
+ import { resolve, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { readFileSync, existsSync } from 'node:fs';
5
+ import { createServer } from 'node:https';
6
+ import { resolveListenerSecurity } from './config/listener-security.js';
7
+ // Load the env file before any other imports read process.env. The CLI passes
8
+ // `--env-file` through MAGNUS_ENV_FILE; otherwise the package-level .env is used
9
+ // when present. Variables already set in the environment always win.
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
11
+ const envFile = process.env['MAGNUS_ENV_FILE'] ? resolve(process.env['MAGNUS_ENV_FILE']) : resolve(__dirname, '../.env');
12
+ if (existsSync(envFile))
13
+ config({ path: envFile, quiet: true });
14
+ // Validate required secrets before starting anything
15
+ const { validateSecrets } = await import('./utils/env.js');
16
+ validateSecrets();
17
+ const { securityFusionLocal, securityFusionMode, startSecurityExporter, stopSecurityExporter } = await import('./services/security-export.js');
18
+ const { featureFlags } = await import('./config/features.js');
19
+ const { serve } = await import('@hono/node-server');
20
+ const { app } = await import('./server.js');
21
+ const { startRolloutReconciler, stopRolloutReconciler } = await import('./services/rollout-service.js');
22
+ const { startApplicationProbes, stopApplicationProbes } = await import('./services/application-probes.js');
23
+ const { startNodeIssueMonitor } = await import('./services/node-issue-monitor.js');
24
+ const { stopNodeIssueMonitor } = await import('./services/node-issue-monitor.js');
25
+ const { startLogRetention } = await import('./services/log-retention.js');
26
+ const { stopLogRetention } = await import('./services/log-retention.js');
27
+ const { startHealthRetention } = await import('./services/health-retention.js');
28
+ const { stopHealthRetention } = await import('./services/health-retention.js');
29
+ const { startNotificationRetention, stopNotificationRetention } = await import('./services/notification-retention.js');
30
+ const { startSecurityFusionRetention, stopSecurityFusionRetention } = await import('./services/security-fusion-service.js');
31
+ const { reconcileSecurityFusionEvidence } = await import('./services/security-fusion-evidence-integrity.js');
32
+ const { startSecurityFusionOutboxDispatcher, stopSecurityFusionOutboxDispatcher, } = await import('./services/security-fusion-outbox.js');
33
+ const { startCommandWorker, closeCommandQueue } = await import('./queue/workers.js');
34
+ const { startWebhookWorker, closeWebhookQueue } = await import('./services/webhook-service.js');
35
+ const { setupTerminalWebSocket } = await import('./routes/terminal.js');
36
+ const { disconnectRedis } = await import('./queue/redis.js');
37
+ const { eventBus } = await import('./services/event-bus.js');
38
+ const { disconnectDb } = await import('./db/index.js');
39
+ const { startCodexFleetMonitor, stopCodexFleetMonitor } = await import('./services/codex-service.js');
40
+ const { startExtensionSourceMonitor, stopExtensionSourceMonitor } = await import('./services/hermes-plugin-source.js');
41
+ const { importPackageSkills } = await import('./services/hermes-catalog-import.js');
42
+ const port = Number(process.env['CONTROL_API_PORT'] ?? 4000);
43
+ const features = featureFlags();
44
+ console.log(`[startup] security-fusion=${securityFusionMode()} hermes-registry=${features.hermesRegistry ? 'on' : 'off'} `
45
+ + `plugin-api=${features.pluginApi ? 'on' : 'off'} iam=${features.iam ? 'on' : 'off'}`);
46
+ if (securityFusionLocal()) {
47
+ const evidenceReconciliation = await reconcileSecurityFusionEvidence();
48
+ console.log(`[security-fusion] evidence reconciliation checked=${evidenceReconciliation.checked} `
49
+ + `updated=${evidenceReconciliation.updated} quarantined=${evidenceReconciliation.quarantined} `
50
+ + `mismatched_cases=${evidenceReconciliation.mismatchedCases}`);
51
+ }
52
+ /** Background services shared by the TLS and development listeners. */
53
+ function startBackgroundServices() {
54
+ startNodeIssueMonitor();
55
+ startApplicationProbes();
56
+ startLogRetention();
57
+ startHealthRetention();
58
+ startNotificationRetention();
59
+ if (securityFusionLocal()) {
60
+ startSecurityFusionRetention();
61
+ startSecurityFusionOutboxDispatcher();
62
+ }
63
+ startSecurityExporter();
64
+ startCommandWorker();
65
+ startRolloutReconciler();
66
+ startWebhookWorker();
67
+ startCodexFleetMonitor();
68
+ if (features.hermesRegistry) {
69
+ startExtensionSourceMonitor();
70
+ void importPackageSkills().then(result => console.log(`[hermes-registry] catalog import: ${JSON.stringify(result)}`))
71
+ .catch(error => console.error('[hermes-registry] catalog import failed', error));
72
+ }
73
+ }
74
+ // Relative TLS paths resolve against the working directory; prefer absolute paths.
75
+ const repoRoot = process.cwd();
76
+ const certPath = process.env['TLS_CERT_PATH']
77
+ ? resolve(repoRoot, process.env['TLS_CERT_PATH'])
78
+ : undefined;
79
+ const keyPath = process.env['TLS_KEY_PATH']
80
+ ? resolve(repoRoot, process.env['TLS_KEY_PATH'])
81
+ : undefined;
82
+ const listener = resolveListenerSecurity({
83
+ nodeEnv: process.env['NODE_ENV'] ?? 'development',
84
+ allowInsecureHttp: (process.env['ALLOW_INSECURE_HTTP'] ?? 'false').toLowerCase() === 'true',
85
+ bindHost: process.env['CONTROL_API_BIND_HOST'],
86
+ certPath,
87
+ keyPath,
88
+ pathExists: existsSync,
89
+ });
90
+ const server = listener.useTls
91
+ ? serve({
92
+ fetch: app.fetch,
93
+ port,
94
+ hostname: listener.hostname,
95
+ createServer,
96
+ serverOptions: {
97
+ key: readFileSync(keyPath),
98
+ cert: readFileSync(certPath),
99
+ },
100
+ }, (info) => {
101
+ console.log(`šŸš€ Magnus server listening on https://${listener.hostname}:${info.port}`);
102
+ startBackgroundServices();
103
+ })
104
+ : serve({ fetch: app.fetch, port, hostname: listener.hostname }, (info) => {
105
+ console.log(`šŸš€ Magnus server listening on http://${listener.hostname}:${info.port} (development opt-in)`);
106
+ startBackgroundServices();
107
+ });
108
+ const terminalWss = setupTerminalWebSocket(server);
109
+ // ── Graceful shutdown ──
110
+ let shuttingDown = false;
111
+ async function shutdown(signal) {
112
+ if (shuttingDown)
113
+ return;
114
+ shuttingDown = true;
115
+ console.log(`\nšŸ›‘ ${signal} received — shutting down Magnus server...`);
116
+ const timeoutMs = Number(process.env['SHUTDOWN_TIMEOUT_MS'] ?? 15_000);
117
+ let deadlineTimer;
118
+ const deadline = new Promise((_, reject) => {
119
+ deadlineTimer = setTimeout(() => reject(new Error(`shutdown exceeded ${timeoutMs}ms`)), timeoutMs);
120
+ });
121
+ let exitCode = 0;
122
+ try {
123
+ await Promise.race([(async () => {
124
+ stopRolloutReconciler();
125
+ stopNodeIssueMonitor();
126
+ stopApplicationProbes();
127
+ stopLogRetention();
128
+ stopHealthRetention();
129
+ stopNotificationRetention();
130
+ stopSecurityFusionRetention();
131
+ stopSecurityExporter();
132
+ stopSecurityFusionOutboxDispatcher();
133
+ stopCodexFleetMonitor();
134
+ stopExtensionSourceMonitor();
135
+ for (const client of terminalWss.clients)
136
+ client.terminate();
137
+ const httpClosed = new Promise((resolvePromise) => server.close(() => resolvePromise()));
138
+ server.closeAllConnections?.();
139
+ const webSocketsClosed = new Promise((resolvePromise) => terminalWss.close(() => resolvePromise()));
140
+ await Promise.all([httpClosed, webSocketsClosed]);
141
+ await closeCommandQueue();
142
+ await closeWebhookQueue();
143
+ await eventBus.close();
144
+ await disconnectRedis();
145
+ await disconnectDb();
146
+ })(), deadline]);
147
+ console.log(' āœ“ HTTP, WebSockets, monitors, queues, Redis, and database closed');
148
+ }
149
+ catch (err) {
150
+ console.error(' āœ— Graceful shutdown failed:', err);
151
+ exitCode = 1;
152
+ }
153
+ finally {
154
+ if (deadlineTimer)
155
+ clearTimeout(deadlineTimer);
156
+ }
157
+ console.log('āœ… Magnus server shutdown complete');
158
+ process.exit(exitCode);
159
+ }
160
+ process.on('SIGTERM', () => void shutdown('SIGTERM'));
161
+ process.on('SIGINT', () => void shutdown('SIGINT'));
162
+ //# sourceMappingURL=index.js.map