fix: require NIP-98 for transcribe endpoints, allow stop during startup

1. P1 — Force NIP-98 signed auth for /transcribe/* endpoints regardless of
   BUZZ_REQUIRE_AUTH_TOKEN. The X-Pubkey dev fallback is spoofable, so a
   billable endpoint must always require cryptographic proof of identity
   before the membership check trusts the pubkey.

2. P2 — DictationButton now allows the stop action whenever isRecording is
   true, even during startup (mic live but SDP exchange in progress) or
   when the composer is disabled. Only blocks the button when idle and
   disabled, or when startup hasn't captured the mic yet.
This commit is contained in:
klopez4212
2026-07-11 16:18:37 +01:00
parent 577b7bb434
commit 955f6871db
2 changed files with 11 additions and 10 deletions
+4 -5
View File
@@ -184,12 +184,11 @@ async fn authenticate(
})?;
let url = super::bridge::nip98_expected_url(&state.config.relay_url, &tenant, path);
// Always require NIP-98 signed auth for transcribe endpoints — these mint
// billable OpenAI sessions, so we cannot trust the unauthenticated X-Pubkey
// dev fallback (which is spoofable) regardless of BUZZ_REQUIRE_AUTH_TOKEN.
let (pubkey, event_id_bytes) = super::bridge::verify_bridge_auth(
headers,
method,
&url,
None,
state.config.require_auth_token,
headers, method, &url, None, true, // force NIP-98 — billable endpoint
)?;
super::bridge::check_nip98_replay(state, &tenant, event_id_bytes).await?;
@@ -28,11 +28,13 @@ export function DictationButton({
? "Transcribing…"
: "Dictate message";
// Allow the stop action even when the composer is disabled — the user must
// always be able to stop an active recording session. Only block *starting*
// a new recording when disabled.
const isDisabled =
dictation.isStarting || (disabled && !dictation.isRecording);
// Allow the stop action whenever the mic is live (isRecording), even if
// the session setup is still in progress (isStarting) or the composer is
// disabled. Only block the button when idle + disabled, or when startup
// hasn't captured the mic yet (isStarting && !isRecording).
const isDisabled = dictation.isRecording
? false
: disabled || dictation.isStarting;
return (
<Tooltip>