Share the guarded huddle publication seam across identity types

Signed-off-by: Bradley Axen <baxen@squareup.com>
This commit is contained in:
Bradley Axen
2026-09-11 18:30:52 -07:00
parent 22f05fc329
commit e0387f5bcb
2 changed files with 14 additions and 20 deletions

View File

@@ -153,8 +153,8 @@ async fn boundary_submit_signed_event_with_keys_blocks_ncryptsec() {
}
/// Boundary 5: huddle STT publisher (`huddle/pipeline.rs`).
#[test]
fn boundary_huddle_stt_blocks_ncryptsec() {
#[tokio::test]
async fn boundary_huddle_stt_blocks_ncryptsec() {
let keys = nostr::Keys::generate();
let channel = uuid::Uuid::new_v4();
let builder = crate::events::build_message(
@@ -170,7 +170,9 @@ fn boundary_huddle_stt_blocks_ncryptsec() {
&crate::relay::relay_api_base_url(),
)
.unwrap();
let err = crate::huddle::pipeline::sign_and_guard_stt_body(builder, &keys).unwrap_err();
let err = crate::huddle::pipeline::sign_and_guard_stt_body(builder, &keys)
.await
.unwrap_err();
assert_guard_error(&err);
// Clean transcripts pass through the same seam.
@@ -187,7 +189,11 @@ fn boundary_huddle_stt_blocks_ncryptsec() {
&crate::relay::relay_api_base_url(),
)
.unwrap();
assert!(crate::huddle::pipeline::sign_and_guard_stt_body(builder, &keys).is_ok());
assert!(
crate::huddle::pipeline::sign_and_guard_stt_body(builder, &keys)
.await
.is_ok()
);
}
/// Boundary 8: native websocket send loop — the single choke point for all

View File

@@ -607,13 +607,11 @@ fn should_reselect_constructed_voice(constructed_voice: &str, latest_voice: &str
/// Factored out of the transcription loop so egress boundary 5 (huddle STT)
/// has a directly testable seam: the NIP-49 egress guard runs here, before
/// any bytes can reach the network.
pub(crate) fn sign_and_guard_stt_body(
pub(crate) async fn sign_and_guard_stt_body(
builder: nostr::EventBuilder,
keys: &nostr::Keys,
identity: impl Into<crate::enterprise_identity::SigningIdentity>,
) -> Result<Vec<u8>, String> {
let event = builder
.sign_with_keys(keys)
.map_err(|e| format!("sign event: {e}"))?;
let event = identity.into().sign(builder).await?;
let body_bytes = event.as_json().into_bytes();
crate::egress_guard::assert_no_key_backup_bytes(&body_bytes, "huddle STT publish")?;
Ok(body_bytes)
@@ -688,17 +686,7 @@ pub(crate) fn spawn_transcription_task(
// the kind event and build NIP-98 auth after the wait so both
// timestamps are fresh — single clean order: wait → sign → auth → send.
crate::relay_admission::wait_for_rate_limit().await;
let signed_body = match &keys {
crate::enterprise_identity::SigningIdentity::Local(keys) => {
sign_and_guard_stt_body(builder, keys)
}
_ => keys.sign(builder).await.and_then(|event| {
let body = event.as_json().into_bytes();
crate::egress_guard::assert_no_key_backup_bytes(&body, "huddle STT publish")?;
Ok(body)
}),
};
let body_bytes = match signed_body {
let body_bytes = match sign_and_guard_stt_body(builder, &keys).await {
Ok(b) => b,
Err(e) => {
eprintln!("buzz-desktop: STT publish: {e}");