diff --git a/app/main.py b/app/main.py index 2c3c101..0e489c5 100644 --- a/app/main.py +++ b/app/main.py @@ -315,6 +315,17 @@ PAGE_HTML = """ } .new-key input:focus { outline: none; border-color: var(--green-mid); } .hint { color: var(--muted); font-size: 12px; margin-top: 10px; } + .key-reveal { + margin-top: 16px; padding: 16px; + background: #eaf3ea; border: 1px solid var(--green-mid); border-radius: 10px; + } + .key-reveal-title { font-weight: 700; font-size: 14px; margin-bottom: 4px; } + .key-reveal-name { color: var(--muted); font-size: 12px; margin-bottom: 8px; } + .key-reveal-value { + display: block; font-family: ui-monospace, 'SF Mono', Menlo, monospace; + font-size: 12px; background: #fff; padding: 8px 10px; border-radius: 6px; + word-break: break-all; margin-bottom: 10px; user-select: all; + } .empty { color: var(--muted); font-size: 14px; padding: 12px 0; } .flash { padding: 12px 16px; border-radius: 8px; margin-top: 16px; font-size: 14px; @@ -397,6 +408,12 @@ PAGE_HTML = """
+ @@ -475,12 +492,12 @@ function renderKeys(keys) { return; } el.innerHTML = keys.map(k => { - const token = k.sk_token || ''; + const fp = k.fingerprint || ''; const created = k.created_at ? ' · created ' + k.created_at.slice(0,10) : ''; return '
' + '
' + escapeHtml(k.name) + '
' + - '
' + escapeHtml(created) + '
' + - (token ? '
' + escapeHtml(token) + '
' : '') + + '
' + escapeHtml(created) + + (fp ? ' · ends …' + escapeHtml(fp) : '') + '
' + '
' + '' + '
'; @@ -503,7 +520,15 @@ async function createKey() { const d = await r.json(); if (d.error) { flash(d.error, false); } else { - flash('Key created — copy it now, it won\u2019t be shown again.', true); + const token = d.sk_token || ''; + if (token) { + // Reveal the key ONCE, inline, copyable. It is never shown again. + const box = $('key-reveal'); + box.style.display = 'block'; + $('key-reveal-value').textContent = token; + $('key-reveal-name').textContent = name; + navigator.clipboard?.writeText(token).catch(() => {}); + } $('new-name').value = ''; load(); }