mirror of
https://github.com/Such-Software/smirk-backend-core.git
synced 2026-10-17 15:31:38 +02:00
feat(relay): gRPC event-admission (nauthz) service enforcing the write policy
nostr-rs-relay's [grpc] event_admission_server calls Authorization.EventAdmit once per inbound event; we answer PERMIT/DENY so the write policy is enforced at ingest (dynamic, per-event — a static pubkey whitelist can't do inbox/PoW). - proto/nauthz.proto (matches nostr-rs-relay's contract) compiled by build.rs; protoc is vendored (protoc-bin-vendored) so a source build needs no system protobuf-compiler. tonic/prost added (reuse the hyper/tower/h2 stack axum already pulls in); server-only codegen. - infra/relay/nauthz: AdmissionService resolves author + recipient (p-tag) registration via the DB, runs the pure policy engine, returns the decision; served on a loopback socket (spawned in main only when relay enabled + policy != open), mirroring the admin plane. Fail-closed on a malformed request. - db: is_registered_npub(hex) — a no-PII membership check safe to call per event. - tests/relay_admission.rs: L1 handler tests (is_registered_npub membership + outbox/inbox/deny-non-giftwrap/deny-unregistered-recipient through the real event_admit handler against live Postgres).
This commit is contained in:
+25
@@ -231,6 +231,31 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
});
|
||||
}
|
||||
|
||||
// Nostr relay event-admission (nauthz) gRPC service — only for a non-`open`
|
||||
// write policy (open needs no admission). Loopback socket, like the admin
|
||||
// plane; nostr-rs-relay is configured to call it per inbound event.
|
||||
if let Some(relay) = state.relay.clone() {
|
||||
use smirk_backend_core::infra::relay::WritePolicy;
|
||||
if relay.write_policy() != WritePolicy::Open {
|
||||
let addr: std::net::SocketAddr = state
|
||||
.config
|
||||
.messaging
|
||||
.relay
|
||||
.admission_bind
|
||||
.parse()
|
||||
.map_err(|e| format!("invalid RELAY_ADMISSION_BIND: {e}"))?;
|
||||
let db = state.db.clone();
|
||||
tracing::info!("relay event-admission (nauthz) listening on {addr}");
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) =
|
||||
smirk_backend_core::infra::relay::nauthz::serve(addr, relay, db).await
|
||||
{
|
||||
tracing::error!(error = %e, "relay admission service exited");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let app = build_router(state);
|
||||
|
||||
let listener = tokio::net::TcpListener::bind(&addr).await?;
|
||||
|
||||
Reference in New Issue
Block a user