Files
jwinterm 63d2c75194 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).
2026-07-02 06:46:59 -04:00

51 lines
1.2 KiB
Protocol Buffer

// nostr-rs-relay event-admission (nauthz) gRPC contract.
//
// This MUST match the proto nostr-rs-relay ships (its `[grpc]
// event_admission_server` calls `Authorization.EventAdmit` once per inbound
// event). Keep field numbers/types identical or the relay cannot talk to us.
// Upstream: nostr-rs-relay/proto/nauthz.proto.
syntax = "proto3";
package nauthz;
// Authorization for actions against a relay.
service Authorization {
// Determine if an event should be admitted to the relay.
rpc EventAdmit(EventRequest) returns (EventReply);
}
message Event {
bytes id = 1;
bytes pubkey = 2;
fixed64 created_at = 3;
uint64 kind = 4;
string content = 5;
repeated TagEntry tags = 6;
bytes sig = 7;
}
message TagEntry {
repeated string values = 1;
}
// Event data + connection metadata for the admission decision.
message EventRequest {
Event event = 1;
optional string ip_addr = 2;
optional string origin = 3;
optional string user_agent = 4;
optional bytes auth_pubkey = 5;
optional string nip05 = 6;
}
message EventReply {
Decision decision = 1;
optional string message = 2;
}
enum Decision {
DECISION_UNSPECIFIED = 0;
DECISION_PERMIT = 1;
DECISION_DENY = 2;
}