types.go raw

   1  // Package directory provides data structures and validation for the distributed
   2  // directory consensus protocol as defined in NIP-XX.
   3  //
   4  // This package implements message encoding and validation for the following
   5  // event kinds:
   6  //   - 39100: Relay Identity Announcement - Announces relay participation in consortium
   7  //   - 39101: Trust Act - Establishes trust relationships with numeric levels (0-100%)
   8  //   - 39102: Group Tag Act - Creates/manages group tags with ownership specs
   9  //   - 39103: Public Key Advertisement - Advertises delegate keys with expiration
  10  //   - 39104: Directory Event Replication Request - Requests event synchronization
  11  //   - 39105: Directory Event Replication Response - Responds to sync requests
  12  //   - 39106: Group Tag Transfer - Transfers group tag ownership (planned)
  13  //   - 39107: Escrow Witness Completion Act - Completes escrow transfers (planned)
  14  //
  15  // # Numeric Trust Levels
  16  //
  17  // Trust levels are represented as numeric values from 0-100, indicating the
  18  // percentage probability that any given event will be replicated. This implements
  19  // partial replication via cryptographic random selection (dice-throw mechanism):
  20  //
  21  //   - 100: Full replication - ALL events replicated (100% probability)
  22  //   - 75:  High partial replication - 75% of events replicated on average
  23  //   - 50:  Medium partial replication - 50% of events replicated on average
  24  //   - 25:  Low partial replication - 25% of events replicated on average
  25  //   - 10:  Minimal sampling - 10% of events replicated on average
  26  //   - 0:   No replication - effectively disables replication
  27  //
  28  // For each event, a cryptographically secure random number (0-100) is generated
  29  // and compared to the trust level threshold. If the random number ≤ trust level,
  30  // the event is replicated; otherwise it is discarded. This provides:
  31  //
  32  //   - Proportional bandwidth/storage reduction
  33  //   - Probabilistic network coverage (events propagate via multiple paths)
  34  //   - Network resilience (different relays replicate different random subsets)
  35  //   - Tunable trade-offs between resources and completeness
  36  //
  37  // # Group Tag Ownership
  38  //
  39  // Group Tag Acts (Kind 39102) establish ownership and control over arbitrary
  40  // string tags, functioning as a first-come-first-served registration system
  41  // akin to domain name registration. Features include:
  42  //
  43  //   - Single signature or multisig ownership (2-of-3, 3-of-5)
  44  //   - URL-safe character validation (RFC 3986 compliance)
  45  //   - Ownership transfer capability (via Kind 39106)
  46  //   - Escrow-based transfer protocol (via Kind 39107)
  47  //   - Foundation for permissioned structured groups across multiple relays
  48  //
  49  // # Legal Concept of Acts
  50  //
  51  // The term "act" in this protocol draws from legal terminology, where an act
  52  // represents a formal declaration or testimony that has legal significance.
  53  // Similar to legal instruments such as:
  54  //
  55  //   - Deed Poll: A legal document binding one party to a particular course of action
  56  //   - Witness Testimony: A formal statement given under oath as evidence
  57  //   - Affidavit: A written statement confirmed by oath for use as evidence
  58  //
  59  // In the context of this protocol, acts serve as cryptographically signed
  60  // declarations that establish trust relationships, group memberships, or other
  61  // formal statements within the relay consortium. Like their legal counterparts,
  62  // these acts:
  63  //
  64  //   - Are formally structured with specific required elements
  65  //   - Carry the authority and responsibility of the signing party
  66  //   - Create binding relationships or obligations within the consortium
  67  //   - Can be verified for authenticity through cryptographic signatures
  68  //   - May have expiration dates or other temporal constraints
  69  //
  70  // This legal framework provides a conceptual foundation for understanding the
  71  // formal nature and binding character of consortium declarations.
  72  package directory
  73  
  74  import (
  75  	"crypto/rand"
  76  	"encoding/hex"
  77  	"time"
  78  
  79  	"next.orly.dev/pkg/lol/chk"
  80  	"next.orly.dev/pkg/lol/errorf"
  81  	"next.orly.dev/pkg/nostr/encoders/event"
  82  	"next.orly.dev/pkg/nostr/encoders/kind"
  83  	"next.orly.dev/pkg/nostr/encoders/tag"
  84  )
  85  
  86  // Event kinds for the distributed directory consensus protocol
  87  var (
  88  	RelayIdentityAnnouncementKind         = kind.New(39100)
  89  	TrustActKind                          = kind.New(39101)
  90  	GroupTagActKind                       = kind.New(39102)
  91  	PublicKeyAdvertisementKind            = kind.New(39103)
  92  	DirectoryEventReplicationRequestKind  = kind.New(39104)
  93  	DirectoryEventReplicationResponseKind = kind.New(39105)
  94  	GroupTagTransferKind                  = kind.New(39106)
  95  	EscrowWitnessCompletionActKind        = kind.New(39107)
  96  )
  97  
  98  // Common tag names used across directory protocol messages.
  99  // These tags are used to structure and encode protocol messages within Nostr events.
 100  var (
 101  	DTag                = []byte("d")                 // Unique identifier for replaceable events
 102  	RelayTag            = []byte("relay")             // WebSocket URL of a relay
 103  	SigningKeyTag       = []byte("signing_key")       // Public key for signature verification
 104  	EncryptionKeyTag    = []byte("encryption_key")    // Public key for ECDH encryption
 105  	VersionTag          = []byte("version")           // Protocol version number
 106  	NIP11URLTag         = []byte("nip11_url")         // Deprecated: Use HTTP GET with Accept header instead
 107  	PubkeyTag           = []byte("p")                 // Public key reference
 108  	TrustLevelTag       = []byte("trust_level")       // Numeric trust level (0-100)
 109  	ExpiryTag           = []byte("expiry")            // Unix timestamp for expiration
 110  	ReasonTag           = []byte("reason")            // Reason for trust establishment
 111  	KTag                = []byte("K")                 // Comma-separated event kinds for replication
 112  	ITag                = []byte("I")                 // Identity tag with proof-of-control
 113  	GroupTagTag         = []byte("group_tag")         // Group identifier and metadata
 114  	ActorTag            = []byte("actor")             // Public key of the actor
 115  	ConfidenceTag       = []byte("confidence")        // Confidence score (0-100)
 116  	OwnersTag           = []byte("owners")            // Ownership specification (scheme + pubkeys)
 117  	CreatedTag          = []byte("created")           // Creation/registration timestamp
 118  	FromOwnersTag       = []byte("from_owners")       // Previous owners in transfer
 119  	ToOwnersTag         = []byte("to_owners")         // New owners in transfer
 120  	TransferDateTag     = []byte("transfer_date")     // Transfer effective date
 121  	SignaturesTag       = []byte("signatures")        // Multisig signatures for transfers
 122  	EscrowIDTag         = []byte("escrow_id")         // Unique escrow identifier
 123  	SellerWitnessTag    = []byte("seller_witness")    // Seller's witness public key
 124  	BuyerWitnessTag     = []byte("buyer_witness")     // Buyer's witness public key
 125  	ConditionsTag       = []byte("conditions")        // Escrow conditions/requirements
 126  	WitnessRoleTag      = []byte("witness_role")      // Role of witness (seller/buyer)
 127  	CompletionStatusTag = []byte("completion_status") // Escrow completion status
 128  	VerificationHashTag = []byte("verification_hash") // Hash for verification
 129  	TimestampTag        = []byte("timestamp")         // General purpose timestamp
 130  	PurposeTag          = []byte("purpose")           // Key purpose (signing/encryption/delegation)
 131  	AlgorithmTag        = []byte("algorithm")         // Cryptographic algorithm identifier
 132  	DerivationPathTag   = []byte("derivation_path")   // BIP32 derivation path
 133  	KeyIndexTag         = []byte("key_index")         // Key index in derivation chain
 134  	RequestIDTag        = []byte("request_id")        // Unique request identifier
 135  	EventIDTag          = []byte("event_id")          // Event ID reference
 136  	StatusTag           = []byte("status")            // Status code (success/error/pending)
 137  	ErrorTag            = []byte("error")             // Error message
 138  )
 139  
 140  // TrustLevel represents the replication percentage (0-100) indicating
 141  // the probability that any given event will be replicated.
 142  //
 143  // This implements partial replication via cryptographic random selection:
 144  // For each event, a secure random number (0-100) is generated and compared
 145  // to the trust level. If random ≤ trust_level, the event is replicated.
 146  //
 147  // Benefits of numeric trust levels:
 148  //   - Precise resource control (bandwidth, storage, CPU)
 149  //   - Probabilistic network coverage via multiple propagation paths
 150  //   - Network resilience through random subset selection
 151  //   - Graceful degradation under resource constraints
 152  //   - Trust inheritance via percentage multiplication (e.g., 75% * 50% = 37.5%)
 153  type TrustLevel uint8
 154  
 155  // Suggested trust level constants for common use cases.
 156  // These are guidelines; any value 0-100 is valid.
 157  const (
 158  	TrustLevelNone    TrustLevel = 0   // No replication (0%)
 159  	TrustLevelMinimal TrustLevel = 10  // Minimal sampling (10%) - network discovery
 160  	TrustLevelLow     TrustLevel = 25  // Low partial replication (25%) - exploratory
 161  	TrustLevelMedium  TrustLevel = 50  // Medium partial replication (50%) - standard
 162  	TrustLevelHigh    TrustLevel = 75  // High partial replication (75%) - important
 163  	TrustLevelFull    TrustLevel = 100 // Full replication (100%) - critical partners
 164  )
 165  
 166  // TrustReason indicates how a trust relationship was established.
 167  // This helps operators understand and audit their trust networks.
 168  type TrustReason string
 169  
 170  const (
 171  	TrustReasonManual    TrustReason = "manual"    // Manually configured by operator
 172  	TrustReasonAutomatic TrustReason = "automatic" // Automatically established by policy
 173  	TrustReasonInherited TrustReason = "inherited" // Inherited through web of trust
 174  )
 175  
 176  // KeyPurpose indicates the intended use of an advertised public key.
 177  // This allows proper key separation and reduces security risks.
 178  type KeyPurpose string
 179  
 180  const (
 181  	KeyPurposeSigning    KeyPurpose = "signing"    // For signing events (BIP-340 Schnorr)
 182  	KeyPurposeEncryption KeyPurpose = "encryption" // For ECDH encryption (NIP-04, NIP-44)
 183  	KeyPurposeDelegation KeyPurpose = "delegation" // For delegated event signing (NIP-26)
 184  )
 185  
 186  // ReplicationStatus indicates the outcome of a replication request.
 187  type ReplicationStatus string
 188  
 189  const (
 190  	ReplicationStatusSuccess ReplicationStatus = "success" // Replication completed successfully
 191  	ReplicationStatusError   ReplicationStatus = "error"   // Replication failed with error
 192  	ReplicationStatusPending ReplicationStatus = "pending" // Replication in progress
 193  )
 194  
 195  // GenerateNonce creates a cryptographically secure random nonce for use in
 196  // identity tags and other protocol messages.
 197  func GenerateNonce(size int) (nonce []byte, err error) {
 198  	if size <= 0 {
 199  		size = 16 // Default to 16 bytes
 200  	}
 201  	nonce = make([]byte, size)
 202  	if _, err = rand.Read(nonce); chk.E(err) {
 203  		return
 204  	}
 205  	return
 206  }
 207  
 208  // GenerateNonceHex creates a hex-encoded nonce of the specified byte size.
 209  func GenerateNonceHex(size int) (nonceHex string, err error) {
 210  	var nonce []byte
 211  	if nonce, err = GenerateNonce(size); chk.E(err) {
 212  		return
 213  	}
 214  	nonceHex = hex.EncodeToString(nonce)
 215  	return
 216  }
 217  
 218  // IsDirectoryEventKind returns true if the given kind is a directory event
 219  // that should always be replicated among consortium members, regardless of
 220  // the trust level's partial replication setting.
 221  //
 222  // Standard Nostr directory events (always replicated):
 223  //   - Kind 0: User Metadata (profiles)
 224  //   - Kind 3: Follow Lists (contact lists)
 225  //   - Kind 5: Event Deletion Requests
 226  //   - Kind 1984: Reporting (spam, abuse reports)
 227  //   - Kind 10002: Relay List Metadata
 228  //   - Kind 10000: Mute Lists
 229  //   - Kind 10050: DM Relay Lists
 230  //
 231  // Protocol-specific directory events (always replicated):
 232  //   - Kind 39100: Relay Identity Announcements
 233  //   - Kind 39101: Trust Acts
 234  //   - Kind 39102: Group Tag Acts
 235  //   - Kind 39103: Public Key Advertisements
 236  //   - Kind 39104: Directory Event Replication Requests
 237  //   - Kind 39105: Directory Event Replication Responses
 238  //   - Kind 39106: Group Tag Transfers
 239  //   - Kind 39107: Escrow Witness Completion Acts
 240  func IsDirectoryEventKind(k uint16) (isDirectory bool) {
 241  	switch k {
 242  	case 0, 3, 5, 1984, 10002, 10000, 10050:
 243  		return true
 244  	case 39100, 39101, 39102, 39103, 39104, 39105, 39106, 39107:
 245  		return true
 246  	default:
 247  		return false
 248  	}
 249  }
 250  
 251  // ValidateTrustLevel checks if the provided trust level is valid (0-100).
 252  // Returns an error if the level exceeds 100.
 253  func ValidateTrustLevel(level TrustLevel) (err error) {
 254  	if level > 100 {
 255  		return errorf.E("invalid trust level: %d (must be 0-100)", level)
 256  	}
 257  	return nil
 258  }
 259  
 260  // ValidateKeyPurpose checks if the provided key purpose is valid.
 261  // Valid purposes are: signing, encryption, delegation.
 262  func ValidateKeyPurpose(purpose string) (err error) {
 263  	switch KeyPurpose(purpose) {
 264  	case KeyPurposeSigning, KeyPurposeEncryption, KeyPurposeDelegation:
 265  		return nil
 266  	default:
 267  		return errorf.E("invalid key purpose: %s", purpose)
 268  	}
 269  }
 270  
 271  // ValidateReplicationStatus checks if the provided replication status is valid.
 272  // Valid statuses are: success, error, pending.
 273  func ValidateReplicationStatus(status string) (err error) {
 274  	switch ReplicationStatus(status) {
 275  	case ReplicationStatusSuccess, ReplicationStatusError, ReplicationStatusPending:
 276  		return nil
 277  	default:
 278  		return errorf.E("invalid replication status: %s", status)
 279  	}
 280  }
 281  
 282  // CreateBaseEvent creates a basic event structure with common fields set.
 283  // This is used as a starting point for constructing protocol messages.
 284  // The event still needs tags, content, and signature to be complete.
 285  func CreateBaseEvent(pubkey []byte, k *kind.K) (ev *event.E) {
 286  	return &event.E{
 287  		Pubkey:    pubkey,
 288  		CreatedAt: time.Now().Unix(),
 289  		Kind:      k.K,
 290  		Tags:      tag.NewS(),
 291  		Content:   []byte(""),
 292  	}
 293  }
 294