test(relay): prove section import privacy boundaries

Co-authored-by: Larry <larry@buzz.invalid>
Signed-off-by: Logan Johnson <loganj@squareup.com>
This commit is contained in:
Logan Johnson
2026-08-21 05:38:17 +00:00
parent a7db357295
commit 39cff6b491
3 changed files with 60 additions and 6 deletions

View File

@@ -457,6 +457,16 @@ mod tests {
.unwrap_err();
assert!(error.to_string().contains("immutable"));
state
.db
.soft_delete_event(tenant.community(), event.id.as_bytes())
.await
.unwrap();
assert!(handle_import(&tenant, &state, &event)
.await
.unwrap()
.message
.starts_with("duplicate:"));
let mut conflicting = import.clone();
conflicting.action_id = uuid::Uuid::new_v4();
assert!(

View File

@@ -28,6 +28,8 @@ const MIGRATION_0007_SQL: &str = include_str!("../../../migrations/0007_nip_rs_r
const MIGRATION_0008_SQL: &str =
include_str!("../../../migrations/0008_fresh_install_search_allowlist.sql");
const MIGRATION_0014_SQL: &str = include_str!("../../../migrations/0014_push_lease_fts.sql");
const MIGRATION_0033_SQL: &str =
include_str!("../../../migrations/0033_section_workspace_projection_fts.sql");
async fn setup() -> (PgPool, String) {
let url = std::env::var("BUZZ_TEST_DATABASE_URL").unwrap_or_else(|_| TEST_DB_URL.to_string());
@@ -81,6 +83,9 @@ async fn setup() -> (PgPool, String) {
pool.execute(MIGRATION_0014_SQL)
.await
.expect("apply 0014 migration");
pool.execute(MIGRATION_0033_SQL)
.await
.expect("apply 0033 migration");
(pool, schema)
}
@@ -1425,6 +1430,20 @@ async fn author_only_kinds_are_storage_level_unsearchable() {
async fn p_gated_persistent_kinds_have_storage_null_tsvector() {
let (pool, schema) = setup().await;
let expression: String = sqlx::query_scalar(
"SELECT pg_get_expr(d.adbin, d.adrelid) \
FROM pg_attrdef d JOIN pg_attribute a \
ON a.attrelid = d.adrelid AND a.attnum = d.adnum \
WHERE d.adrelid = 'events'::regclass AND a.attname = 'search_tsv'",
)
.fetch_one(&pool)
.await
.expect("read migration 0033 generated expression");
assert!(
expression.contains("9050") && expression.contains("30623"),
"{expression}"
);
let c = mk_community(&pool, "p-gated-tripwire.example").await;
let token = "pgated_tripwire_marker_qwerty";

View File

@@ -2,10 +2,12 @@
use std::time::Duration;
use base64::{engine::general_purpose::STANDARD as BASE64, Engine};
use buzz_test_client::BuzzTestClient;
use nostr::{Alphabet, Event, EventBuilder, Filter, Keys, Kind, SingleLetterTag, Tag};
use reqwest::Client;
use serde_json::{json, Value};
use sha2::{Digest, Sha256};
const IMPORT_KIND: u16 = 9050;
const PROJECTION_KIND: u16 = 30623;
@@ -37,11 +39,31 @@ async fn ws_query(client: &mut BuzzTestClient, name: &str, filter: Filter) -> Ve
.unwrap()
}
fn nip98(keys: &Keys, url: &str, body: &str) -> String {
let payload = hex::encode(Sha256::digest(body.as_bytes()));
let event = EventBuilder::new(Kind::Custom(27_235), "")
.tags([
Tag::parse(["u", url]).unwrap(),
Tag::parse(["method", "POST"]).unwrap(),
Tag::parse(["payload", &payload]).unwrap(),
Tag::parse(["nonce", &uuid::Uuid::new_v4().to_string()]).unwrap(),
])
.sign_with_keys(keys)
.unwrap();
format!(
"Nostr {}",
BASE64.encode(serde_json::to_string(&event).unwrap())
)
}
async fn http_query(http: &Client, reader: &Keys, filter: Filter) -> Vec<Value> {
let url = format!("{}/query", http_url());
let body = serde_json::to_string(&vec![filter]).unwrap();
let response = http
.post(format!("{}/query", http_url()))
.header("X-Pubkey", reader.public_key().to_hex())
.json(&vec![filter])
.post(&url)
.header("Authorization", nip98(reader, &url, &body))
.header("Content-Type", "application/json")
.body(body)
.send()
.await
.unwrap();
@@ -54,10 +76,13 @@ async fn http_query(http: &Client, reader: &Keys, filter: Filter) -> Vec<Value>
}
async fn http_count(http: &Client, reader: &Keys, filter: Filter) -> u64 {
let url = format!("{}/count", http_url());
let body = serde_json::to_string(&vec![filter]).unwrap();
let response = http
.post(format!("{}/count", http_url()))
.header("X-Pubkey", reader.public_key().to_hex())
.json(&vec![filter])
.post(&url)
.header("Authorization", nip98(reader, &url, &body))
.header("Content-Type", "application/json")
.body(body)
.send()
.await
.unwrap();