mirror of
https://github.com/block/buzz.git
synced 2026-11-06 01:11:33 +00:00
test(relay): bind durable revocation to socket admission
Authenticate through root and audio handlers before a durable-only ban. Removing either production enrollment call must fail its regression. Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Brad Seiler <seiler@squareup.com>
This commit is contained in:
@@ -15966,6 +15966,37 @@ mod tests {
|
||||
server.abort();
|
||||
}
|
||||
|
||||
/// Binds durable revocation to the real audio AUTH enrollment call.
|
||||
#[tokio::test]
|
||||
#[ignore = "requires Postgres — runs in postgres-ci nextest lane"]
|
||||
async fn durable_ban_revalidates_real_audio_admission_without_delivery() {
|
||||
let state = audio_test_state_real_db()
|
||||
.await
|
||||
.expect("isolated PostgreSQL");
|
||||
let (tenant, channel_id, member) = seed_audio_fixture(state.db.pool()).await;
|
||||
let (mut client, server) =
|
||||
open_admitted_audio_socket(&state, tenant.clone(), channel_id, &member, None).await;
|
||||
state
|
||||
.db
|
||||
.ban_community_member(
|
||||
tenant.community(),
|
||||
member.public_key().as_bytes(),
|
||||
member.public_key().as_bytes(),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.expect("commit ban only");
|
||||
assert_eq!(
|
||||
state.revalidate_live_authorizations().await,
|
||||
1,
|
||||
"real audio admission must enroll the socket in durable scans"
|
||||
);
|
||||
expect_policy_close(&mut client).await;
|
||||
server.abort();
|
||||
let _ = server.await;
|
||||
}
|
||||
|
||||
/// Every frame up to and including the server's close.
|
||||
async fn audio_frames_until_close(
|
||||
client: &mut tokio_tungstenite::WebSocketStream<
|
||||
|
||||
@@ -3140,6 +3140,63 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// Binds the durable scan to real AUTH enrollment, with Redis unavailable.
|
||||
#[tokio::test]
|
||||
#[ignore = "requires Postgres — runs in postgres-ci nextest lane"]
|
||||
async fn durable_ban_revalidates_real_root_admission_without_delivery() {
|
||||
let state = auth_test_state_real_db_expect().await;
|
||||
let community = seeded_community(&state).await;
|
||||
let (member, owner, agent, bystander) = (
|
||||
Keys::generate(),
|
||||
Keys::generate(),
|
||||
Keys::generate(),
|
||||
Keys::generate(),
|
||||
);
|
||||
let tag = buzz_sdk::nip_oa::compute_auth_tag(&owner, &agent.public_key(), "")
|
||||
.expect("owner proof");
|
||||
let tag = serde_json::from_str(&tag).expect("owner tag JSON");
|
||||
let mut connections = Vec::new();
|
||||
for (keys, tag, challenge) in [
|
||||
(&member, None, "durable-member"),
|
||||
(&agent, Some(tag), "durable-agent"),
|
||||
(&bystander, None, "durable-bystander"),
|
||||
] {
|
||||
let (conn, _control) = registered_pending_conn(&state, community, challenge);
|
||||
handle_auth(
|
||||
signed_auth(keys, challenge, tag),
|
||||
Arc::clone(&conn),
|
||||
Arc::clone(&state),
|
||||
)
|
||||
.await;
|
||||
assert!(matches!(
|
||||
conn.auth_state_snapshot(),
|
||||
AuthState::Authenticated(_)
|
||||
));
|
||||
connections.push(conn);
|
||||
}
|
||||
for key in [&member, &owner] {
|
||||
state
|
||||
.db
|
||||
.ban_community_member(
|
||||
community,
|
||||
key.public_key().as_bytes(),
|
||||
bystander.public_key().as_bytes(),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.expect("commit ban only");
|
||||
}
|
||||
assert!(connections.iter().all(|conn| !conn.cancel.is_cancelled()));
|
||||
assert_eq!(state.revalidate_live_authorizations().await, 2);
|
||||
assert!(connections[0].cancel.is_cancelled(), "direct member closes");
|
||||
assert!(
|
||||
connections[1].cancel.is_cancelled(),
|
||||
"owner-linked agent closes"
|
||||
);
|
||||
assert!(!connections[2].cancel.is_cancelled(), "bystander stays");
|
||||
}
|
||||
|
||||
/// AUTH with NIP-OA records a previously ownerless agent's owner. That
|
||||
/// closes the agent's earlier ownerless socket so it reconnects with
|
||||
/// the owner attached, but not the socket being admitted, even when
|
||||
|
||||
Reference in New Issue
Block a user