feat: Hermes prompt callback endpoint + API key management

- Add /api/prompt/<rid> callback endpoint with dual auth:
  per-request signed URL token + Bearer API key.
- Add HERMES_API_KEY config and runtime key helpers in app.py.
- Update admin request page to copy request details + callback URL.
- Add API key management to admin settings: regenerate, mask, show-once.
- Update .env.example, docker-compose.yml, README, REVIEW docs.
This commit is contained in:
Troll (Hermes Agent) 2026-08-03 17:16:56 +00:00
parent e46893e0b4
commit 6a60aa686c
8 changed files with 242 additions and 35 deletions

View file

@ -251,6 +251,28 @@
</form>
</div>
<!-- Email / SMTP configuration -->
<div class="section">
<h2>Hermes API Key</h2>
<p class="copy-hint">Hermes uses this key in the Authorization header when POSTing generated Suno prompts back to the callback endpoint.</p>
<p><strong>Current key:</strong> <code>{{ hermes_key_masked }}</code></p>
{% if hermes_key_just_generated %}
<div class="flash success" style="background:#064e3b">
<p><strong>New key (copy it now — it will not be shown again):</strong></p>
<p class="path" id="new-hermes-key">{{ hermes_key_just_generated }}</p>
<button type="button" onclick="copyHermesKey()">Copy to clipboard</button>
</div>
{% elif not hermes_key_set %}
<p class="status-bad">⚠️ No Hermes API key is configured. Generate one before using the callback workflow.</p>
{% endif %}
<form method="POST" onsubmit="return confirm('Regenerating the key will invalidate the old one. Hermes will need the new key. Continue?')">
<input type="hidden" name="action" value="regenerate_hermes_key">
<button type="submit">Regenerate API Key</button>
</form>
</div>
<!-- Email / SMTP configuration -->
<div class="section">
<h2>Email (SMTP) Settings</h2>
@ -351,8 +373,22 @@
<button type="submit">Reset System</button>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
<script>
function copyHermesKey() {
const el = document.getElementById('new-hermes-key');
if (!el) return;
const range = document.createRange();
range.selectNode(el);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
navigator.clipboard.writeText(el.textContent).then(() => {
alert('Hermes API key copied!');
});
}
</script>
</body>
</html>