From 656748ea286ff7eac6cbe1b241ad31212892ba61 Mon Sep 17 00:00:00 2001 From: bndw Date: Fri, 13 Feb 2026 19:12:28 -0800 Subject: feat: implement NIP-09 (deletions) and NIP-11 (relay info) NIP-11 (Relay Information Document): - Serves relay metadata at GET / with Accept: application/nostr+json - Returns name, description, supported NIPs, limitations - CORS headers for browser compatibility NIP-09 (Event Deletion): - Kind 5 events delete events referenced in 'e' tags - Only authors can delete their own events - Soft delete (marks deleted=1) - Records deletion in deletions table - Works across all protocols (gRPC, Connect, WebSocket) Fixed deletions schema: - deleted_event_id as PRIMARY KEY (not deletion_event_id) - Allows one deletion event to delete multiple events 3 new tests, 44 total tests passing Supported NIPs now: 1, 9, 11 --- internal/handler/grpc/server.go | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'internal/handler/grpc/server.go') diff --git a/internal/handler/grpc/server.go b/internal/handler/grpc/server.go index b65b527..b1ffd96 100644 --- a/internal/handler/grpc/server.go +++ b/internal/handler/grpc/server.go @@ -13,6 +13,7 @@ import ( type EventStore interface { StoreEvent(context.Context, *storage.EventData) error QueryEvents(context.Context, []*pb.Filter, *storage.QueryOptions) ([]*pb.Event, error) + ProcessDeletion(context.Context, *pb.Event) error } type Server struct { @@ -75,6 +76,16 @@ func (s *Server) PublishEvent(ctx context.Context, req *pb.PublishEventRequest) return nil, fmt.Errorf("failed to store event: %w", err) } + if req.Event.Kind == 5 { + if err := s.store.ProcessDeletion(ctx, req.Event); err != nil { + return &pb.PublishEventResponse{ + Accepted: false, + Message: fmt.Sprintf("deletion processing failed: %v", err), + CanonicalJson: canonicalJSON, + }, nil + } + } + s.subs.MatchAndFan(req.Event) return &pb.PublishEventResponse{ -- cgit v1.2.3