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