@geekbeer/minion 2.56.1 → 2.58.1

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.
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Sudoers endpoint
3
+ *
4
+ * Endpoints:
5
+ * - GET /api/sudoers - List sudo permissions for the current user
6
+ */
7
+
8
+ const { exec } = require('child_process')
9
+ const { promisify } = require('util')
10
+ const execAsync = promisify(exec)
11
+
12
+ const { verifyToken } = require('../lib/auth')
13
+
14
+ /**
15
+ * Parse `sudo -l` output into structured permission entries
16
+ * @param {string} output - Raw output from `sudo -l`
17
+ * @returns {string[]} List of allowed commands
18
+ */
19
+ function parseSudoList(output) {
20
+ const lines = output.split('\n')
21
+ const commands = []
22
+
23
+ for (const line of lines) {
24
+ const trimmed = line.trim()
25
+ // Lines starting with (root) contain permission entries
26
+ if (trimmed.startsWith('(root)') || trimmed.startsWith('(ALL)')) {
27
+ // Extract the command part after NOPASSWD: or the run-as spec
28
+ const match = trimmed.match(/(?:NOPASSWD:\s*)(.+)$/)
29
+ if (match) {
30
+ commands.push(match[1].trim())
31
+ }
32
+ }
33
+ }
34
+
35
+ return commands
36
+ }
37
+
38
+ /**
39
+ * Register sudoers routes as Fastify plugin
40
+ * @param {import('fastify').FastifyInstance} fastify
41
+ */
42
+ async function sudoersRoutes(fastify) {
43
+ fastify.get('/api/sudoers', async (request, reply) => {
44
+ if (!verifyToken(request)) {
45
+ reply.code(401)
46
+ return { success: false, error: 'Unauthorized' }
47
+ }
48
+
49
+ try {
50
+ const { stdout } = await execAsync('sudo -n -l 2>/dev/null', { timeout: 5000 })
51
+ const commands = parseSudoList(stdout)
52
+
53
+ return {
54
+ success: true,
55
+ commands,
56
+ raw: stdout.trim(),
57
+ }
58
+ } catch (error) {
59
+ // sudo -l may fail if sudo is not configured at all
60
+ return {
61
+ success: true,
62
+ commands: [],
63
+ raw: '',
64
+ note: 'sudo is not configured or no permissions granted',
65
+ }
66
+ }
67
+ })
68
+ }
69
+
70
+ module.exports = { sudoersRoutes }
@@ -323,7 +323,12 @@ do_setup() {
323
323
  echo "${TARGET_USER} ALL=(root) NOPASSWD: ${NPM_BIN} install -g @geekbeer/minion@latest"
324
324
  echo "${TARGET_USER} ALL=(root) NOPASSWD: ${NPM_BIN} install -g @geekbeer/minion@latest --registry *"
325
325
  echo "${TARGET_USER} ALL=(root) NOPASSWD: /usr/bin/apt-get install *"
326
+ echo "${TARGET_USER} ALL=(root) NOPASSWD: /usr/bin/apt-get update"
326
327
  echo "${TARGET_USER} ALL=(root) NOPASSWD: /usr/bin/apt-get remove *"
328
+ # Allow sh -c wrappers (used by playwright install-deps, etc.)
329
+ echo "${TARGET_USER} ALL=(root) NOPASSWD: /bin/sh -c *apt-get*"
330
+ echo "${TARGET_USER} ALL=(root) NOPASSWD: /usr/bin/sh -c *apt-get*"
331
+ echo "${TARGET_USER} ALL=(root) NOPASSWD: /bin/sh -c *dpkg*"
327
332
 
328
333
  case "$PROC_MGR" in
329
334
  systemd)
package/linux/server.js CHANGED
@@ -20,6 +20,7 @@
20
20
  * Secrets: GET /api/secrets, PUT/DELETE /api/secrets/:key
21
21
  * Config: GET /api/config/backup, GET/PUT /api/config/env
22
22
  * Executions: GET /api/executions, GET /api/executions/:id, etc.
23
+ * Sudoers: GET /api/sudoers
23
24
  * ─────────────────────────────────────────────────────────────────────────────
24
25
  */
25
26
 
@@ -65,6 +66,7 @@ const { authRoutes } = require('../core/routes/auth')
65
66
  const { variableRoutes } = require('../core/routes/variables')
66
67
  const { memoryRoutes } = require('../core/routes/memory')
67
68
  const { dailyLogRoutes } = require('../core/routes/daily-logs')
69
+ const { sudoersRoutes } = require('../core/routes/sudoers')
68
70
 
69
71
  // Linux-specific routes
70
72
  const { commandRoutes, getProcessManager, getAllowedCommands } = require('./routes/commands')
@@ -265,6 +267,7 @@ async function registerAllRoutes(app) {
265
267
  await app.register(variableRoutes)
266
268
  await app.register(memoryRoutes)
267
269
  await app.register(dailyLogRoutes)
270
+ await app.register(sudoersRoutes)
268
271
 
269
272
  // Linux-specific routes
270
273
  await app.register(commandRoutes)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geekbeer/minion",
3
- "version": "2.56.1",
3
+ "version": "2.58.1",
4
4
  "description": "AI Agent runtime for Minion - manages status and skill deployment on VPS",
5
5
  "main": "linux/server.js",
6
6
  "bin": {