superacli 1.1.23 → 1.1.26

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 (128) hide show
  1. package/.beads/.br_history/{issues.20260427_104638_898729442.jsonl → issues.20260428_172005_240631447.jsonl} +102 -102
  2. package/.beads/.br_history/{issues.20260427_104638_209211116.jsonl → issues.20260430_073641_144807989.jsonl} +103 -102
  3. package/.beads/.br_history/{issues.20260427_104637_752744777.jsonl → issues.20260430_073642_807075699.jsonl} +104 -102
  4. package/.beads/.br_history/{issues.20260427_104615_669652069.jsonl → issues.20260430_073645_625754223.jsonl} +105 -102
  5. package/.beads/.br_history/issues.20260430_090639_154646058.jsonl +265 -0
  6. package/.beads/.br_history/issues.20260430_090640_350560318.jsonl +266 -0
  7. package/.beads/.br_history/issues.20260430_090641_509319001.jsonl +267 -0
  8. package/.beads/.br_history/issues.20260430_095140_396749398.jsonl +268 -0
  9. package/.beads/.br_history/issues.20260501_230041_334056077.jsonl +269 -0
  10. package/.beads/issues.jsonl +9 -0
  11. package/graphify-out/GRAPH_REPORT.md +158 -138
  12. package/graphify-out/cache/036077d325d5aa25fc6ad7f01ca32721b02e3f981231f67fb22f59380063572b.json +1 -0
  13. package/graphify-out/cache/5262fb95a8855fc90efbfff767eb3aacca82c4da5799605a969554580a255404.json +1 -0
  14. package/graphify-out/cache/68e2b11c95ede4f05b88d001040008cb3ac72d7bd27f351497c87e128fb3b221.json +1 -0
  15. package/graphify-out/cache/8308aa47b396b929d5b896051ca91422afdde4861108d6f18f5094901093df79.json +1 -0
  16. package/graphify-out/cache/9832101a7622924f58b9e7d7752b41518049447171f7955e4c50dfd386574e12.json +1 -0
  17. package/graphify-out/cache/b849fb88344c2f88f3d22e42b67516e071c7d1e65f77f4ca23f25af6edfca3b3.json +1 -0
  18. package/graphify-out/cache/f9ee11f4395cb41b6f6900079cb7e94297c89b1b0b4798398d2f7a2e244c683b.json +1 -0
  19. package/graphify-out/graph.json +705 -678
  20. package/package.json +1 -1
  21. package/plugins/bluebuild/install-guidance.json +11 -0
  22. package/plugins/bluebuild/meta.json +5 -0
  23. package/plugins/bluebuild/plugin.json +99 -0
  24. package/plugins/bluebuild/skills/quickstart/SKILL.md +47 -0
  25. package/plugins/cargo-public-api/install-guidance.json +11 -0
  26. package/plugins/cargo-public-api/meta.json +5 -0
  27. package/plugins/cargo-public-api/plugin.json +88 -0
  28. package/plugins/cargo-public-api/skills/quickstart/SKILL.md +51 -0
  29. package/plugins/csview/install-guidance.json +11 -0
  30. package/plugins/csview/meta.json +5 -0
  31. package/plugins/csview/plugin.json +67 -0
  32. package/plugins/csview/skills/quickstart/SKILL.md +51 -0
  33. package/plugins/cymbal/install-guidance.json +11 -0
  34. package/plugins/cymbal/meta.json +5 -0
  35. package/plugins/cymbal/plugin.json +121 -0
  36. package/plugins/cymbal/skills/quickstart/SKILL.md +54 -0
  37. package/plugins/difftastic/install-guidance.json +11 -0
  38. package/plugins/difftastic/meta.json +5 -0
  39. package/plugins/difftastic/plugin.json +87 -0
  40. package/plugins/difftastic/skills/quickstart/SKILL.md +53 -0
  41. package/plugins/dlm/install-guidance.json +11 -0
  42. package/plugins/dlm/meta.json +5 -0
  43. package/plugins/dlm/plugin.json +85 -0
  44. package/plugins/dlm/skills/quickstart/SKILL.md +49 -0
  45. package/plugins/dofigen/install-guidance.json +11 -0
  46. package/plugins/dofigen/meta.json +5 -0
  47. package/plugins/dofigen/plugin.json +84 -0
  48. package/plugins/dofigen/skills/quickstart/SKILL.md +50 -0
  49. package/plugins/http-nu/install-guidance.json +11 -0
  50. package/plugins/http-nu/meta.json +5 -0
  51. package/plugins/http-nu/plugin.json +84 -0
  52. package/plugins/http-nu/skills/quickstart/SKILL.md +52 -0
  53. package/plugins/hwatch/install-guidance.json +11 -0
  54. package/plugins/hwatch/meta.json +5 -0
  55. package/plugins/hwatch/plugin.json +100 -0
  56. package/plugins/hwatch/skills/quickstart/SKILL.md +54 -0
  57. package/plugins/hyperfine/install-guidance.json +3 -3
  58. package/plugins/hyperfine/meta.json +2 -2
  59. package/plugins/hyperfine/plugin.json +39 -16
  60. package/plugins/hyperfine/skills/quickstart/SKILL.md +33 -61
  61. package/plugins/json5/install-guidance.json +12 -0
  62. package/plugins/json5/meta.json +5 -0
  63. package/plugins/json5/plugin.json +88 -0
  64. package/plugins/json5/skills/quickstart/SKILL.md +55 -0
  65. package/plugins/mdsf/install-guidance.json +11 -0
  66. package/plugins/mdsf/meta.json +5 -0
  67. package/plugins/mdsf/plugin.json +101 -0
  68. package/plugins/mdsf/skills/quickstart/SKILL.md +55 -0
  69. package/plugins/oha/install-guidance.json +11 -0
  70. package/plugins/oha/meta.json +5 -0
  71. package/plugins/oha/plugin.json +67 -0
  72. package/plugins/oha/skills/quickstart/SKILL.md +44 -0
  73. package/plugins/pv-migrate/install-guidance.json +11 -0
  74. package/plugins/pv-migrate/meta.json +5 -0
  75. package/plugins/pv-migrate/plugin.json +102 -0
  76. package/plugins/pv-migrate/skills/quickstart/SKILL.md +58 -0
  77. package/plugins/rash/install-guidance.json +11 -0
  78. package/plugins/rash/meta.json +5 -0
  79. package/plugins/rash/plugin.json +85 -0
  80. package/plugins/rash/skills/quickstart/SKILL.md +46 -0
  81. package/plugins/rsonpath/install-guidance.json +11 -0
  82. package/plugins/rsonpath/meta.json +5 -0
  83. package/plugins/rsonpath/plugin.json +87 -0
  84. package/plugins/rsonpath/skills/quickstart/SKILL.md +44 -0
  85. package/plugins/rsql/install-guidance.json +11 -0
  86. package/plugins/rsql/meta.json +5 -0
  87. package/plugins/rsql/plugin.json +84 -0
  88. package/plugins/rsql/skills/quickstart/SKILL.md +52 -0
  89. package/plugins/temporal/install-guidance.json +11 -0
  90. package/plugins/temporal/meta.json +5 -0
  91. package/plugins/temporal/plugin.json +95 -0
  92. package/plugins/temporal/skills/quickstart/SKILL.md +49 -0
  93. package/plugins/tkn/install-guidance.json +11 -0
  94. package/plugins/tkn/meta.json +5 -0
  95. package/plugins/tkn/plugin.json +98 -0
  96. package/plugins/tkn/skills/quickstart/SKILL.md +50 -0
  97. package/plugins/toml2json/install-guidance.json +11 -0
  98. package/plugins/toml2json/meta.json +5 -0
  99. package/plugins/toml2json/plugin.json +85 -0
  100. package/plugins/toml2json/skills/quickstart/SKILL.md +47 -0
  101. package/plugins/worktrunk/install-guidance.json +11 -0
  102. package/plugins/worktrunk/meta.json +5 -0
  103. package/plugins/worktrunk/plugin.json +116 -0
  104. package/plugins/worktrunk/skills/quickstart/SKILL.md +62 -0
  105. package/server/app.js +5 -4
  106. package/server/middleware/auth.js +4 -4
  107. package/server/routes/clients.js +46 -0
  108. package/server/routes/plugins.js +0 -116
  109. package/server/routes/settings.js +93 -0
  110. package/server/views/api-keys.ejs +147 -0
  111. package/server/views/layout.ejs +37 -0
  112. package/server/views/partials/head.ejs +3 -1
  113. package/server/views/plugins.ejs +1 -80
  114. package/server/views/settings.ejs +99 -0
  115. package/.beads/.br_history/issues.20260427_104606_658098709.jsonl +0 -261
  116. package/.beads/.br_history/issues.20260427_104607_085798670.jsonl +0 -261
  117. package/.beads/.br_history/issues.20260427_104607_627598880.jsonl +0 -261
  118. package/.beads/.br_history/issues.20260427_104608_071298223.jsonl +0 -261
  119. package/.beads/.br_history/issues.20260427_104615_198124329.jsonl +0 -261
  120. /package/.beads/.br_history/{issues.20260427_104606_658098709.jsonl.meta.json → issues.20260428_172005_240631447.jsonl.meta.json} +0 -0
  121. /package/.beads/.br_history/{issues.20260427_104607_085798670.jsonl.meta.json → issues.20260430_073641_144807989.jsonl.meta.json} +0 -0
  122. /package/.beads/.br_history/{issues.20260427_104607_627598880.jsonl.meta.json → issues.20260430_073642_807075699.jsonl.meta.json} +0 -0
  123. /package/.beads/.br_history/{issues.20260427_104608_071298223.jsonl.meta.json → issues.20260430_073645_625754223.jsonl.meta.json} +0 -0
  124. /package/.beads/.br_history/{issues.20260427_104615_198124329.jsonl.meta.json → issues.20260430_090639_154646058.jsonl.meta.json} +0 -0
  125. /package/.beads/.br_history/{issues.20260427_104615_669652069.jsonl.meta.json → issues.20260430_090640_350560318.jsonl.meta.json} +0 -0
  126. /package/.beads/.br_history/{issues.20260427_104637_752744777.jsonl.meta.json → issues.20260430_090641_509319001.jsonl.meta.json} +0 -0
  127. /package/.beads/.br_history/{issues.20260427_104638_209211116.jsonl.meta.json → issues.20260430_095140_396749398.jsonl.meta.json} +0 -0
  128. /package/.beads/.br_history/{issues.20260427_104638_898729442.jsonl.meta.json → issues.20260501_230041_334056077.jsonl.meta.json} +0 -0
@@ -0,0 +1,147 @@
1
+ <%- include("partials/head", { title: "API Keys" }) %>
2
+
3
+ <div id="api-keys-app" class="max-w-4xl">
4
+ <div class="flex justify-between items-center mb-6">
5
+ <h1 class="text-2xl font-bold">API Keys</h1>
6
+ <div class="text-sm opacity-80">Manage API keys for CLI and programmatic access.</div>
7
+ </div>
8
+
9
+ <div v-if="message.text" :class="['alert mb-4', message.type === 'error' ? 'alert-error' : 'alert-success']">
10
+ <span>{{ message.text }}</span>
11
+ </div>
12
+
13
+ <div class="card bg-base-100 border border-base-300">
14
+ <div class="card-body">
15
+ <h2 class="card-title">Create New API Key</h2>
16
+ <div class="form-control">
17
+ <div class="label">
18
+ <span class="label-text">Key Name</span>
19
+ </div>
20
+ <div class="flex gap-2">
21
+ <input v-model="newKeyName" class="input input-bordered flex-1" placeholder="e.g., 'CLI Agent' or 'Production'" />
22
+ <button class="btn btn-primary" @click="createApiKey">Create</button>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ </div>
27
+
28
+ <div class="card bg-base-100 border border-base-300 mt-4">
29
+ <div class="card-body">
30
+ <h2 class="card-title">Active API Keys</h2>
31
+ <div v-if="settings.api_keys && settings.api_keys.length > 0">
32
+ <table class="table table-zebra">
33
+ <thead>
34
+ <tr>
35
+ <th>Name</th>
36
+ <th>Key</th>
37
+ <th>Created</th>
38
+ <th>Action</th>
39
+ </tr>
40
+ </thead>
41
+ <tbody>
42
+ <tr v-for="apiKey in settings.api_keys" :key="apiKey.key">
43
+ <td>{{ apiKey.name }}</td>
44
+ <td>
45
+ <code>{{ apiKey.key.slice(0, 12) }}...</code>
46
+ <button class="btn btn-xs btn-ghost ml-2" @click="copyApiKey(apiKey.key)">📋</button>
47
+ </td>
48
+ <td>{{ new Date(apiKey.created_at).toLocaleString() }}</td>
49
+ <td>
50
+ <button class="btn btn-sm btn-error" @click="deleteApiKey(apiKey.key)">Delete</button>
51
+ </td>
52
+ </tr>
53
+ </tbody>
54
+ </table>
55
+ </div>
56
+ <div v-else class="text-center py-8 opacity-60">
57
+ <p>No API keys created yet</p>
58
+ <p class="text-sm mt-2">Create an API key to enable CLI and programmatic access to the server.</p>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ </div>
63
+
64
+ <script>
65
+ const { createApp } = Vue
66
+
67
+ createApp({
68
+ data() {
69
+ return {
70
+ settings: {},
71
+ newKeyName: '',
72
+ message: { text: '', type: 'success' }
73
+ }
74
+ },
75
+ async mounted() {
76
+ await this.loadSettings()
77
+ },
78
+ methods: {
79
+ async loadSettings() {
80
+ try {
81
+ const res = await fetch('/api/settings?format=json')
82
+ const data = await res.json()
83
+ this.settings = data
84
+ } catch (err) {
85
+ this.setMessage('error', err.message)
86
+ }
87
+ },
88
+ async createApiKey() {
89
+ if (!this.newKeyName.trim()) {
90
+ this.setMessage('error', 'API key name is required')
91
+ return
92
+ }
93
+ try {
94
+ const res = await fetch('/api/api-keys', {
95
+ method: 'POST',
96
+ headers: { 'Content-Type': 'application/json' },
97
+ body: JSON.stringify({ name: this.newKeyName })
98
+ })
99
+ const result = await res.json()
100
+ this.setMessage('success', `Created API key '${result.name}'`)
101
+ this.newKeyName = ''
102
+ await this.loadSettings()
103
+ } catch (err) {
104
+ this.setMessage('error', err.message)
105
+ }
106
+ },
107
+ async deleteApiKey(key) {
108
+ if (!confirm('Delete this API key?')) return
109
+ try {
110
+ await fetch(`/api/api-keys/${encodeURIComponent(key)}`, {
111
+ method: 'DELETE'
112
+ })
113
+ this.setMessage('success', 'API key deleted')
114
+ await this.loadSettings()
115
+ } catch (err) {
116
+ this.setMessage('error', err.message)
117
+ }
118
+ },
119
+ async copyApiKey(key) {
120
+ try {
121
+ // Fallback for non-HTTPS contexts
122
+ const textArea = document.createElement("textarea")
123
+ textArea.value = key
124
+ textArea.style.position = "fixed"
125
+ textArea.style.left = "-9999px"
126
+ document.body.appendChild(textArea)
127
+ textArea.select()
128
+ try {
129
+ document.execCommand("copy")
130
+ this.setMessage('success', 'API key copied to clipboard')
131
+ } catch (err) {
132
+ throw new Error('Copy failed')
133
+ }
134
+ document.body.removeChild(textArea)
135
+ } catch (err) {
136
+ this.setMessage('error', 'Failed to copy API key')
137
+ }
138
+ },
139
+ setMessage(type, text) {
140
+ this.message = { type, text }
141
+ setTimeout(() => this.message = { text: '', type: 'success' }, 3000)
142
+ }
143
+ }
144
+ }).mount('#api-keys-app')
145
+ </script>
146
+
147
+ <%- include("partials/foot") %>
@@ -88,6 +88,43 @@
88
88
  <body>
89
89
 
90
90
  <div class="flex min-h-screen">
91
+ <!-- Sidebar navigation -->
92
+ <aside class="w-64 bg-white border-r border-[#EAEAEA] p-6">
93
+ <div class="mb-8">
94
+ <h1 class="text-xl font-bold editorial-heading">SUPERCLI</h1>
95
+ <p class="text-sm text-[#787774]">Command Control Plane</p>
96
+ </div>
97
+ <nav class="space-y-2">
98
+ <a href="/api/plugins" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
99
+ Plugins
100
+ </a>
101
+ <a href="/api/settings" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
102
+ Settings
103
+ </a>
104
+ <a href="/api/api-keys" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
105
+ API Keys
106
+ </a>
107
+ <a href="/api/commands" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
108
+ Commands
109
+ </a>
110
+ <a href="/api/jobs" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
111
+ Jobs
112
+ </a>
113
+ <a href="/api/clients" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
114
+ Clients
115
+ </a>
116
+ <a href="/api/adapters" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
117
+ Adapters
118
+ </a>
119
+ <a href="/api/specs" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
120
+ OpenAPI Specs
121
+ </a>
122
+ <a href="/api/mcp" class="block px-4 py-2 rounded-lg hover:bg-[#F7F6F3] transition-colors">
123
+ MCP Servers
124
+ </a>
125
+ </nav>
126
+ </aside>
127
+
91
128
  <!-- Main content -->
92
129
  <main class="flex-1 p-8 bg-[#FBFBFA]">
93
130
  <%- body %>
@@ -98,7 +98,9 @@
98
98
  <a href="/api/specs" class="btn justify-start" id="nav-specs">OpenAPI Specs</a>
99
99
  <a href="/api/mcp" class="btn justify-start" id="nav-mcp">MCP Servers</a>
100
100
  <a href="/api/plugins" class="btn justify-start" id="nav-plugins">Server Plugins</a>
101
- <a href="/api/plugins/clients" class="btn justify-start" id="nav-clients">Clients</a>
101
+ <a href="/api/settings" class="btn justify-start" id="nav-settings">Settings</a>
102
+ <a href="/api/api-keys" class="btn justify-start" id="nav-api-keys">API Keys</a>
103
+ <a href="/api/clients" class="btn justify-start" id="nav-clients">Clients</a>
102
104
  <a href="/api/jobs" class="btn justify-start" id="nav-jobs">Jobs</a>
103
105
  <a href="/api/docs" class="btn justify-start" id="nav-docs">Documentation</a>
104
106
  </aside>
@@ -15,76 +15,7 @@
15
15
  <span><strong>Admin Mode Enabled:</strong> CLI clients can modify server state without authentication. Disable when not needed.</span>
16
16
  </div>
17
17
 
18
- <div class="grid grid-cols-1 lg:grid-cols-3 gap-4 mb-6">
19
- <div class="card bg-base-100 border border-base-300">
20
- <div class="card-body p-4">
21
- <h2 class="card-title text-base">Settings</h2>
22
- <label class="form-control mb-2">
23
- <span class="label-text text-xs">Max ZIP Size (MB)</span>
24
- <input v-model.number="settings.max_zip_mb" type="number" min="1" class="input input-bordered input-sm" />
25
- </label>
26
- <label class="form-control mb-3">
27
- <span class="label-text text-xs">Default Hooks Policy</span>
28
- <select v-model="settings.default_hooks_policy" class="select select-bordered select-sm">
29
- <option value="deny">deny</option>
30
- <option value="allow">allow</option>
31
- </select>
32
- </label>
33
- <label class="label cursor-pointer justify-start gap-2 mb-3">
34
- <input type="checkbox" v-model="settings.admin_mode_enabled" class="checkbox checkbox-error checkbox-sm" />
35
- <span class="label-text text-xs text-error font-semibold">Admin Mode (allows CLI modifications)</span>
36
- </label>
37
- <label class="label cursor-pointer justify-start gap-2 mb-3">
38
- <input type="checkbox" v-model="settings.public_access" class="checkbox checkbox-sm" />
39
- <span class="label-text text-xs">Public Access (allow without API key)</span>
40
- </label>
41
- <button class="btn btn-sm btn-primary" @click="saveSettings">Save Settings</button>
42
- </div>
43
- </div>
44
-
45
- <div class="card bg-base-100 border border-base-300">
46
- <div class="card-body p-4">
47
- <h2 class="card-title text-base">API Keys</h2>
48
- <div class="form-control mb-3">
49
- <div class="label">
50
- <span class="label-text text-xs">Create New API Key</span>
51
- </div>
52
- <div class="flex gap-2">
53
- <input v-model="newKeyName" class="input input-bordered input-sm flex-1" placeholder="Key name (e.g., 'CLI Agent')" />
54
- <button class="btn btn-sm btn-primary" @click="createApiKey">Create</button>
55
- </div>
56
- </div>
57
- <div v-if="settings.api_keys && settings.api_keys.length > 0" class="overflow-x-auto">
58
- <table class="table table-zebra table-xs">
59
- <thead>
60
- <tr>
61
- <th>Name</th>
62
- <th>Key</th>
63
- <th>Created</th>
64
- <th>Action</th>
65
- </tr>
66
- </thead>
67
- <tbody>
68
- <tr v-for="apiKey in settings.api_keys" :key="apiKey.key">
69
- <td>{{ apiKey.name }}</td>
70
- <td>
71
- <code class="text-xs">{{ apiKey.key.slice(0, 8) }}...</code>
72
- <button class="btn btn-xs btn-ghost ml-1" @click="copyApiKey(apiKey.key)">📋</button>
73
- </td>
74
- <td class="text-xs">{{ new Date(apiKey.created_at).toLocaleDateString() }}</td>
75
- <td>
76
- <button class="btn btn-xs btn-error" @click="deleteApiKey(apiKey.key)">Delete</button>
77
- </td>
78
- </tr>
79
- </tbody>
80
- </table>
81
- </div>
82
- <div v-else class="text-xs opacity-60 text-center py-2">
83
- No API keys created yet
84
- </div>
85
- </div>
86
- </div>
87
-
18
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-4 mb-6">
88
19
  <div class="card bg-base-100 border border-base-300">
89
20
  <div class="card-body p-4">
90
21
  <h2 class="card-title text-base">Create JSON Plugin</h2>
@@ -201,7 +132,6 @@
201
132
  archive_file: null,
202
133
  manifestStr: '{\n "name": "my-plugin",\n "version": "0.0.0",\n "commands": []\n}',
203
134
  },
204
- newKeyName: '',
205
135
  }
206
136
  },
207
137
  methods: {
@@ -228,15 +158,6 @@
228
158
  this.plugins = out.plugins || []
229
159
  if (out.settings) this.settings = out.settings
230
160
  },
231
- async saveSettings() {
232
- try {
233
- await this.api('/api/plugins/settings', 'PUT', this.settings)
234
- this.setMessage('success', 'Settings updated')
235
- await this.reloadPlugins()
236
- } catch (err) {
237
- this.setMessage('error', err.message)
238
- }
239
- },
240
161
  async createJsonPlugin() {
241
162
  try {
242
163
  const manifest = JSON.parse(this.jsonForm.manifestStr)
@@ -0,0 +1,99 @@
1
+ <%- include("partials/head", { title: "Server Settings" }) %>
2
+
3
+ <div id="settings-app" class="max-w-4xl">
4
+ <div class="flex justify-between items-center mb-6">
5
+ <h1 class="text-2xl font-bold">Server Settings</h1>
6
+ <div class="text-sm opacity-80">Configure server-wide behavior and security.</div>
7
+ </div>
8
+
9
+ <div v-if="message.text" :class="['alert mb-4', message.type === 'error' ? 'alert-error' : 'alert-success']">
10
+ <span>{{ message.text }}</span>
11
+ </div>
12
+
13
+ <div v-if="settings.admin_mode_enabled" class="alert alert-error mb-4">
14
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 shrink-0 stroke-current" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /></svg>
15
+ <span><strong>Admin Mode Enabled:</strong> CLI clients can modify server state without authentication. Disable when not needed.</span>
16
+ </div>
17
+
18
+ <div class="card bg-base-100 border border-base-300">
19
+ <div class="card-body">
20
+ <h2 class="card-title">General Settings</h2>
21
+ <label class="form-control mb-3">
22
+ <span class="label-text">Max ZIP Size (MB)</span>
23
+ <input v-model.number="settings.max_zip_mb" type="number" min="1" class="input input-bordered" />
24
+ </label>
25
+ <label class="form-control mb-3">
26
+ <span class="label-text">Default Hooks Policy</span>
27
+ <select v-model="settings.default_hooks_policy" class="select select-bordered">
28
+ <option value="deny">deny</option>
29
+ <option value="allow">allow</option>
30
+ </select>
31
+ </label>
32
+ </div>
33
+ </div>
34
+
35
+ <div class="card bg-base-100 border border-base-300 mt-4">
36
+ <div class="card-body">
37
+ <h2 class="card-title">Security Settings</h2>
38
+ <label class="label cursor-pointer justify-start gap-2 mb-3">
39
+ <input type="checkbox" v-model="settings.admin_mode_enabled" class="checkbox checkbox-error" />
40
+ <span class="label-text text-error font-semibold">Admin Mode (allows CLI modifications without auth)</span>
41
+ </label>
42
+ <label class="label cursor-pointer justify-start gap-2 mb-3">
43
+ <input type="checkbox" v-model="settings.public_access" class="checkbox" />
44
+ <span class="label-text">Public Access (allow API requests without API key)</span>
45
+ </label>
46
+ </div>
47
+ </div>
48
+
49
+ <div class="mt-6">
50
+ <button class="btn btn-primary" @click="saveSettings">Save Settings</button>
51
+ </div>
52
+ </div>
53
+
54
+ <script>
55
+ const { createApp } = Vue
56
+
57
+ createApp({
58
+ data() {
59
+ return {
60
+ settings: {},
61
+ message: { text: '', type: 'success' }
62
+ }
63
+ },
64
+ async mounted() {
65
+ await this.loadSettings()
66
+ },
67
+ methods: {
68
+ async loadSettings() {
69
+ try {
70
+ const res = await fetch('/api/settings?format=json')
71
+ const data = await res.json()
72
+ this.settings = data
73
+ } catch (err) {
74
+ this.setMessage('error', err.message)
75
+ }
76
+ },
77
+ async saveSettings() {
78
+ try {
79
+ const res = await fetch('/api/settings', {
80
+ method: 'PUT',
81
+ headers: { 'Content-Type': 'application/json' },
82
+ body: JSON.stringify(this.settings)
83
+ })
84
+ const data = await res.json()
85
+ this.settings = data.settings
86
+ this.setMessage('success', 'Settings saved')
87
+ } catch (err) {
88
+ this.setMessage('error', err.message)
89
+ }
90
+ },
91
+ setMessage(type, text) {
92
+ this.message = { type, text }
93
+ setTimeout(() => this.message = { text: '', type: 'success' }, 3000)
94
+ }
95
+ }
96
+ }).mount('#settings-app')
97
+ </script>
98
+
99
+ <%- include("partials/foot") %>