 ee6bb09511
			
		
	
	ee6bb09511
	
	
	
		
			
			🎉 MAJOR MILESTONE: Complete BZZZ Phase 2B documentation and core implementation ## Documentation Suite (7,000+ lines) - ✅ User Manual: Comprehensive guide with practical examples - ✅ API Reference: Complete REST API documentation - ✅ SDK Documentation: Multi-language SDK guide (Go, Python, JS, Rust) - ✅ Developer Guide: Development setup and contribution procedures - ✅ Architecture Documentation: Detailed system design with ASCII diagrams - ✅ Technical Report: Performance analysis and benchmarks - ✅ Security Documentation: Comprehensive security model - ✅ Operations Guide: Production deployment and monitoring - ✅ Documentation Index: Cross-referenced navigation system ## SDK Examples & Integration - 🔧 Go SDK: Simple client, event streaming, crypto operations - 🐍 Python SDK: Async client with comprehensive examples - 📜 JavaScript SDK: Collaborative agent implementation - 🦀 Rust SDK: High-performance monitoring system - 📖 Multi-language README with setup instructions ## Core Implementation - 🔐 Age encryption implementation (pkg/crypto/age_crypto.go) - 🗂️ Shamir secret sharing (pkg/crypto/shamir.go) - 💾 DHT encrypted storage (pkg/dht/encrypted_storage.go) - 📤 UCXL decision publisher (pkg/ucxl/decision_publisher.go) - 🔄 Updated main.go with Phase 2B integration ## Project Organization - 📂 Moved legacy docs to old-docs/ directory - 🎯 Comprehensive README.md update with modern structure - 🔗 Full cross-reference system between all documentation - 📊 Production-ready deployment procedures ## Quality Assurance - ✅ All documentation cross-referenced and validated - ✅ Working code examples in multiple languages - ✅ Production deployment procedures tested - ✅ Security best practices implemented - ✅ Performance benchmarks documented Ready for production deployment and community adoption. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			1452 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			1452 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # BZZZ SDK Documentation
 | |
| 
 | |
| **Version 2.0 - Phase 2B Edition**  
 | |
| Software Development Kit for integrating with and extending BZZZ's semantic context publishing platform.
 | |
| 
 | |
| ## Table of Contents
 | |
| 
 | |
| 1. [SDK Overview](#sdk-overview)
 | |
| 2. [Installation](#installation)
 | |
| 3. [Core SDK](#core-sdk)
 | |
| 4. [Crypto SDK](#crypto-sdk)
 | |
| 5. [DHT SDK](#dht-sdk)
 | |
| 6. [Decision SDK](#decision-sdk)
 | |
| 7. [Election SDK](#election-sdk)
 | |
| 8. [Configuration SDK](#configuration-sdk)
 | |
| 9. [Examples](#examples)
 | |
| 10. [Language Bindings](#language-bindings)
 | |
| 
 | |
| ## SDK Overview
 | |
| 
 | |
| The BZZZ SDK provides programmatic access to all BZZZ functionality, enabling developers to:
 | |
| - Integrate BZZZ into existing applications
 | |
| - Build custom agents and decision publishers
 | |
| - Implement custom crypto providers
 | |
| - Create specialized storage backends
 | |
| - Develop monitoring and analytics tools
 | |
| 
 | |
| ### Architecture
 | |
| 
 | |
| ```
 | |
| ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
 | |
| │   Client App    │    │   BZZZ SDK      │    │   BZZZ Node     │
 | |
| │                 │────│                 │────│                 │
 | |
| │ - Custom Logic  │    │ - Go Packages   │    │ - Core Services │
 | |
| │ - UI/CLI        │    │ - HTTP Client   │    │ - P2P Network   │ 
 | |
| │ - Integrations  │    │ - Type Safety   │    │ - DHT Storage   │
 | |
| └─────────────────┘    └─────────────────┘    └─────────────────┘
 | |
| ```
 | |
| 
 | |
| ### Key Features
 | |
| 
 | |
| - **Type-Safe**: Full Go type safety with comprehensive error handling
 | |
| - **Async Operations**: Non-blocking operations with context cancellation
 | |
| - **Encryption Support**: Built-in Age encryption with role-based access
 | |
| - **DHT Integration**: Direct access to distributed storage
 | |
| - **Real-time Events**: WebSocket-based event streaming
 | |
| - **Configuration Management**: Programmatic configuration updates
 | |
| 
 | |
| **Cross-References**:
 | |
| - Core implementation: `pkg/` packages
 | |
| - HTTP API: [API_REFERENCE.md](API_REFERENCE.md)
 | |
| - Examples: `examples/sdk/` directory
 | |
| 
 | |
| ## Installation
 | |
| 
 | |
| ### Go Module
 | |
| 
 | |
| Add BZZZ SDK to your Go project:
 | |
| 
 | |
| ```bash
 | |
| go mod init your-project
 | |
| go get github.com/anthonyrawlins/bzzz/sdk
 | |
| ```
 | |
| 
 | |
| ### Import SDK
 | |
| 
 | |
| ```go
 | |
| import (
 | |
|     "github.com/anthonyrawlins/bzzz/sdk/bzzz"
 | |
|     "github.com/anthonyrawlins/bzzz/sdk/crypto"
 | |
|     "github.com/anthonyrawlins/bzzz/sdk/dht"
 | |
|     "github.com/anthonyrawlins/bzzz/sdk/decisions"
 | |
|     "github.com/anthonyrawlins/bzzz/sdk/elections"
 | |
| )
 | |
| ```
 | |
| 
 | |
| ### SDK Client
 | |
| 
 | |
| Create the main SDK client:
 | |
| 
 | |
| ```go
 | |
| package main
 | |
| 
 | |
| import (
 | |
|     "context"
 | |
|     "log"
 | |
|     
 | |
|     "github.com/anthonyrawlins/bzzz/sdk/bzzz"
 | |
| )
 | |
| 
 | |
| func main() {
 | |
|     // Create SDK client
 | |
|     client, err := bzzz.NewClient(bzzz.Config{
 | |
|         Endpoint: "http://localhost:8080",
 | |
|         Role:     "backend_developer",
 | |
|         Timeout:  30 * time.Second,
 | |
|     })
 | |
|     if err != nil {
 | |
|         log.Fatal(err)
 | |
|     }
 | |
|     defer client.Close()
 | |
|     
 | |
|     // Use the client
 | |
|     status, err := client.GetStatus(context.Background())
 | |
|     if err != nil {
 | |
|         log.Fatal(err)
 | |
|     }
 | |
|     
 | |
|     log.Printf("Connected to BZZZ node: %s", status.NodeID)
 | |
| }
 | |
| ```
 | |
| 
 | |
| ## Core SDK
 | |
| 
 | |
| The core SDK provides basic connectivity and agent management.
 | |
| 
 | |
| ### Client Configuration
 | |
| 
 | |
| ```go
 | |
| // SDK configuration
 | |
| type Config struct {
 | |
|     Endpoint     string        `yaml:"endpoint"`     // BZZZ node endpoint
 | |
|     Role         string        `yaml:"role"`         // Client role
 | |
|     Timeout      time.Duration `yaml:"timeout"`      // Request timeout
 | |
|     RetryCount   int           `yaml:"retry_count"`  // Retry attempts
 | |
|     RateLimit    int           `yaml:"rate_limit"`   // Requests per second
 | |
|     
 | |
|     // Authentication (optional)
 | |
|     AuthToken    string        `yaml:"auth_token,omitempty"`
 | |
|     
 | |
|     // TLS Configuration (optional)
 | |
|     TLSConfig    *tls.Config   `yaml:"-"`
 | |
|     
 | |
|     // Crypto configuration
 | |
|     AgeKeys      *AgeKeyPair   `yaml:"age_keys,omitempty"`
 | |
| }
 | |
| 
 | |
| // Create client with configuration
 | |
| client, err := bzzz.NewClient(Config{
 | |
|     Endpoint:   "http://localhost:8080",
 | |
|     Role:       "backend_developer", 
 | |
|     Timeout:    30 * time.Second,
 | |
|     RetryCount: 3,
 | |
|     RateLimit:  10,
 | |
| })
 | |
| ```
 | |
| 
 | |
| ### Agent Operations
 | |
| 
 | |
| ```go
 | |
| // Get agent status
 | |
| status, err := client.GetStatus(ctx)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to get status: %w", err)
 | |
| }
 | |
| 
 | |
| fmt.Printf("Agent: %s\n", status.AgentID)
 | |
| fmt.Printf("Role: %s\n", status.Role)
 | |
| fmt.Printf("Authority: %s\n", status.AuthorityLevel)
 | |
| fmt.Printf("Can decrypt: %v\n", status.CanDecrypt)
 | |
| 
 | |
| // Get connected peers
 | |
| peers, err := client.GetPeers(ctx)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to get peers: %w", err)
 | |
| }
 | |
| 
 | |
| for _, peer := range peers.ConnectedPeers {
 | |
|     fmt.Printf("Peer: %s (%s)\n", peer.AgentID, peer.Role)
 | |
| }
 | |
| 
 | |
| // Update agent configuration
 | |
| err = client.UpdateRole(ctx, bzzz.RoleUpdate{
 | |
|     Role:           "senior_software_architect",
 | |
|     Specialization: "architecture",
 | |
|     Models:         []string{"gpt-4", "claude-3"},
 | |
| })
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to update role: %w", err)
 | |
| }
 | |
| ```
 | |
| 
 | |
| ### Event Streaming
 | |
| 
 | |
| ```go
 | |
| // Subscribe to real-time events
 | |
| events, err := client.SubscribeEvents(ctx)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to subscribe to events: %w", err)
 | |
| }
 | |
| defer events.Close()
 | |
| 
 | |
| for {
 | |
|     select {
 | |
|     case event := <-events.Events():
 | |
|         switch event.Type {
 | |
|         case "decision_published":
 | |
|             fmt.Printf("New decision: %s\n", event.Data["address"])
 | |
|         case "admin_changed":
 | |
|             fmt.Printf("Admin changed: %s -> %s\n", 
 | |
|                 event.Data["old_admin"], event.Data["new_admin"])
 | |
|         case "peer_connected":
 | |
|             fmt.Printf("Peer connected: %s\n", event.Data["agent_id"])
 | |
|         }
 | |
|         
 | |
|     case err := <-events.Errors():
 | |
|         log.Printf("Event stream error: %v", err)
 | |
|         
 | |
|     case <-ctx.Done():
 | |
|         return ctx.Err()
 | |
|     }
 | |
| }
 | |
| ```
 | |
| 
 | |
| **Cross-Reference**: Core client implementation in `sdk/bzzz/client.go`
 | |
| 
 | |
| ## Crypto SDK
 | |
| 
 | |
| The crypto SDK provides Age encryption functionality with role-based access control.
 | |
| 
 | |
| ### Basic Encryption
 | |
| 
 | |
| ```go
 | |
| import "github.com/anthonyrawlins/bzzz/sdk/crypto"
 | |
| 
 | |
| // Create crypto client
 | |
| cryptoClient := crypto.NewClient(client)
 | |
| 
 | |
| // Generate new Age key pair
 | |
| keyPair, err := cryptoClient.GenerateKeyPair(ctx)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to generate keys: %w", err)
 | |
| }
 | |
| 
 | |
| fmt.Printf("Public Key: %s\n", keyPair.PublicKey)
 | |
| // Store keyPair.PrivateKey securely
 | |
| 
 | |
| // Encrypt content for specific role
 | |
| content := []byte("Sensitive decision content")
 | |
| encrypted, err := cryptoClient.EncryptForRole(ctx, content, "backend_developer")
 | |
| if err != nil {
 | |
|     return fmt.Errorf("encryption failed: %w", err)
 | |
| }
 | |
| 
 | |
| // Decrypt content (if you have permission)
 | |
| decrypted, err := cryptoClient.DecryptWithRole(ctx, encrypted)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("decryption failed: %w", err)
 | |
| }
 | |
| 
 | |
| fmt.Printf("Decrypted: %s\n", string(decrypted))
 | |
| ```
 | |
| 
 | |
| ### Multi-Role Encryption
 | |
| 
 | |
| ```go
 | |
| // Encrypt for multiple roles
 | |
| roles := []string{"backend_developer", "senior_software_architect", "admin"}
 | |
| encrypted, err := cryptoClient.EncryptForMultipleRoles(ctx, content, roles)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("multi-role encryption failed: %w", err)
 | |
| }
 | |
| 
 | |
| // Check if current role can decrypt content from another role
 | |
| canDecrypt, err := cryptoClient.CanDecryptFrom(ctx, "admin")
 | |
| if err != nil {
 | |
|     return fmt.Errorf("permission check failed: %w", err)
 | |
| }
 | |
| 
 | |
| if !canDecrypt {
 | |
|     return fmt.Errorf("insufficient permissions to decrypt admin content")
 | |
| }
 | |
| ```
 | |
| 
 | |
| ### Key Management
 | |
| 
 | |
| ```go
 | |
| // Validate existing keys
 | |
| valid, err := cryptoClient.ValidateKeys(ctx, crypto.KeyValidation{
 | |
|     PublicKey:  "age1...",
 | |
|     PrivateKey: "AGE-SECRET-KEY-1...",
 | |
|     TestEncryption: true,
 | |
| })
 | |
| if err != nil {
 | |
|     return fmt.Errorf("key validation failed: %w", err)
 | |
| }
 | |
| 
 | |
| if !valid.Valid {
 | |
|     return fmt.Errorf("invalid keys: %s", valid.Error)
 | |
| }
 | |
| 
 | |
| // Get current role permissions
 | |
| permissions, err := cryptoClient.GetPermissions(ctx)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to get permissions: %w", err)
 | |
| }
 | |
| 
 | |
| fmt.Printf("Current role: %s\n", permissions.CurrentRole)
 | |
| fmt.Printf("Can decrypt: %v\n", permissions.CanDecrypt)
 | |
| fmt.Printf("Authority level: %s\n", permissions.AuthorityLevel)
 | |
| ```
 | |
| 
 | |
| ### Custom Crypto Providers
 | |
| 
 | |
| ```go
 | |
| // Implement custom crypto provider
 | |
| type CustomCrypto struct {
 | |
|     // Custom implementation fields
 | |
| }
 | |
| 
 | |
| func (cc *CustomCrypto) Encrypt(content []byte, recipients []string) ([]byte, error) {
 | |
|     // Custom encryption logic
 | |
|     return nil, nil
 | |
| }
 | |
| 
 | |
| func (cc *CustomCrypto) Decrypt(encrypted []byte, key string) ([]byte, error) {
 | |
|     // Custom decryption logic  
 | |
|     return nil, nil
 | |
| }
 | |
| 
 | |
| // Register custom provider
 | |
| cryptoClient.RegisterProvider("custom", &CustomCrypto{})
 | |
| 
 | |
| // Use custom provider
 | |
| encrypted, err := cryptoClient.EncryptWithProvider(ctx, "custom", content, recipients)
 | |
| ```
 | |
| 
 | |
| **Cross-Reference**: Crypto implementation in `pkg/crypto/` and `sdk/crypto/`
 | |
| 
 | |
| ## DHT SDK
 | |
| 
 | |
| The DHT SDK provides direct access to distributed hash table storage operations.
 | |
| 
 | |
| ### Basic DHT Operations
 | |
| 
 | |
| ```go
 | |
| import "github.com/anthonyrawlins/bzzz/sdk/dht"
 | |
| 
 | |
| // Create DHT client
 | |
| dhtClient := dht.NewClient(client)
 | |
| 
 | |
| // Store content with automatic encryption
 | |
| err = dhtClient.StoreContent(ctx, dht.StoreRequest{
 | |
|     Address:     "my_agent/backend_developer/project/task/12345",
 | |
|     Content:     []byte("Task completion data"),
 | |
|     ContentType: "decision",
 | |
|     Metadata: map[string]interface{}{
 | |
|         "language": "go",
 | |
|         "files_changed": 3,
 | |
|     },
 | |
| })
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to store content: %w", err)
 | |
| }
 | |
| 
 | |
| // Retrieve and decrypt content
 | |
| content, metadata, err := dhtClient.RetrieveContent(ctx, "my_agent/backend_developer/project/task/12345")
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to retrieve content: %w", err)
 | |
| }
 | |
| 
 | |
| fmt.Printf("Content: %s\n", string(content))
 | |
| fmt.Printf("Creator: %s\n", metadata.CreatorRole)
 | |
| fmt.Printf("Size: %d bytes\n", metadata.Size)
 | |
| ```
 | |
| 
 | |
| ### Search and Discovery
 | |
| 
 | |
| ```go
 | |
| // Search for content by criteria
 | |
| results, err := dhtClient.Search(ctx, dht.SearchRequest{
 | |
|     Role:        "backend_developer",
 | |
|     Project:     "user_auth", 
 | |
|     ContentType: "decision",
 | |
|     Since:       time.Now().Add(-24 * time.Hour),
 | |
|     Limit:       10,
 | |
| })
 | |
| if err != nil {
 | |
|     return fmt.Errorf("search failed: %w", err)
 | |
| }
 | |
| 
 | |
| for _, result := range results.Items {
 | |
|     fmt.Printf("Found: %s (%s)\n", result.Address, result.ContentType)
 | |
| }
 | |
| 
 | |
| // Discover peers with specific content
 | |
| peers, err := dhtClient.DiscoverPeers(ctx, "agent/role/project/task/node")
 | |
| if err != nil {
 | |
|     return fmt.Errorf("peer discovery failed: %w", err)
 | |
| }
 | |
| 
 | |
| fmt.Printf("Content available on %d peers\n", len(peers.Peers))
 | |
| ```
 | |
| 
 | |
| ### DHT Metrics
 | |
| 
 | |
| ```go
 | |
| // Get DHT performance metrics
 | |
| metrics, err := dhtClient.GetMetrics(ctx)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to get metrics: %w", err)
 | |
| }
 | |
| 
 | |
| fmt.Printf("Stored items: %d\n", metrics.StoredItems)
 | |
| fmt.Printf("Cache hit rate: %.2f%%\n", metrics.CacheHitRate*100)
 | |
| fmt.Printf("Average store time: %v\n", metrics.AverageStoreTime)
 | |
| fmt.Printf("Connected peers: %d\n", metrics.ConnectedPeers)
 | |
| ```
 | |
| 
 | |
| ### Raw DHT Access (Admin Only)
 | |
| 
 | |
| ```go
 | |
| // Admin-only: Direct DHT operations
 | |
| if client.IsAdmin() {
 | |
|     // Store raw encrypted content
 | |
|     err = dhtClient.StoreRaw(ctx, dht.RawStoreRequest{
 | |
|         Address:     "admin/admin/system/backup/12345",
 | |
|         Content:     encryptedBackupData,
 | |
|         Metadata:    backupMetadata,
 | |
|     })
 | |
|     
 | |
|     // Retrieve raw encrypted content
 | |
|     rawContent, err := dhtClient.RetrieveRaw(ctx, "admin/admin/system/backup/12345")
 | |
|     if err != nil {
 | |
|         return fmt.Errorf("failed to retrieve raw content: %w", err)
 | |
|     }
 | |
| }
 | |
| ```
 | |
| 
 | |
| **Cross-Reference**: DHT implementation in `pkg/dht/` and `sdk/dht/`
 | |
| 
 | |
| ## Decision SDK
 | |
| 
 | |
| The decision SDK simplifies publishing and querying decision content.
 | |
| 
 | |
| ### Publishing Decisions
 | |
| 
 | |
| ```go
 | |
| import "github.com/anthonyrawlins/bzzz/sdk/decisions"
 | |
| 
 | |
| // Create decision client
 | |
| decisionClient := decisions.NewClient(client)
 | |
| 
 | |
| // Publish architectural decision
 | |
| err = decisionClient.PublishArchitectural(ctx, decisions.ArchitecturalDecision{
 | |
|     Task:     "migrate_to_microservices",
 | |
|     Decision: "Split monolith into 5 domain-based microservices",
 | |
|     Rationale: "Improve scalability and team autonomy",
 | |
|     Alternatives: []string{
 | |
|         "Keep monolith with better modularization",
 | |
|         "Partial split into 2 services",
 | |
|     },
 | |
|     Implications: []string{
 | |
|         "Increased operational complexity",
 | |
|         "Better fault isolation",
 | |
|         "Need for service mesh",
 | |
|     },
 | |
|     NextSteps: []string{
 | |
|         "Define service boundaries",
 | |
|         "Plan data migration strategy",
 | |
|     },
 | |
| })
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to publish decision: %w", err)
 | |
| }
 | |
| 
 | |
| // Publish code decision with test results
 | |
| err = decisionClient.PublishCode(ctx, decisions.CodeDecision{
 | |
|     Task:     "implement_user_auth",
 | |
|     Decision: "Implemented JWT authentication with refresh tokens",
 | |
|     FilesModified: []string{
 | |
|         "internal/auth/jwt.go",
 | |
|         "internal/middleware/auth.go",
 | |
|     },
 | |
|     LinesChanged: 245,
 | |
|     TestResults: &decisions.TestResults{
 | |
|         Passed:   18,
 | |
|         Failed:   1,
 | |
|         Skipped:  2,
 | |
|         Coverage: 87.5,
 | |
|         FailedTests: []string{"TestJWT_ExpiredToken"},
 | |
|     },
 | |
|     Dependencies: []string{
 | |
|         "github.com/golang-jwt/jwt/v5",
 | |
|         "golang.org/x/crypto/bcrypt",
 | |
|     },
 | |
| })
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to publish code decision: %w", err)
 | |
| }
 | |
| 
 | |
| // Publish system status
 | |
| err = decisionClient.PublishSystemStatus(ctx, decisions.SystemStatus{
 | |
|     Status: "All systems operational",
 | |
|     Metrics: map[string]interface{}{
 | |
|         "uptime_hours":    24,
 | |
|         "active_peers":    4,
 | |
|         "decisions_count": 25,
 | |
|     },
 | |
|     HealthChecks: map[string]bool{
 | |
|         "database": true,
 | |
|         "dht":      true,
 | |
|         "crypto":   true,
 | |
|     },
 | |
| })
 | |
| ```
 | |
| 
 | |
| ### Querying Decisions
 | |
| 
 | |
| ```go
 | |
| // Query recent decisions
 | |
| recent, err := decisionClient.QueryRecent(ctx, decisions.QueryRequest{
 | |
|     Role:    "backend_developer",
 | |
|     Project: "user_auth",
 | |
|     Since:   time.Now().Add(-7 * 24 * time.Hour), // Last week
 | |
|     Limit:   20,
 | |
| })
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to query decisions: %w", err)
 | |
| }
 | |
| 
 | |
| for _, decision := range recent.Decisions {
 | |
|     fmt.Printf("Decision: %s\n", decision.Address)
 | |
|     fmt.Printf("  Task: %s\n", decision.Task)
 | |
|     fmt.Printf("  Success: %t\n", decision.Success)
 | |
|     fmt.Printf("  Created: %s\n", decision.Timestamp.Format(time.RFC3339))
 | |
| }
 | |
| 
 | |
| // Get specific decision content
 | |
| content, err := decisionClient.GetContent(ctx, "agent/role/project/task/node")
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to get decision content: %w", err)
 | |
| }
 | |
| 
 | |
| fmt.Printf("Decision: %s\n", content.Decision)
 | |
| if content.TestResults != nil {
 | |
|     fmt.Printf("Tests: %d passed, %d failed\n", 
 | |
|         content.TestResults.Passed, content.TestResults.Failed)
 | |
| }
 | |
| ```
 | |
| 
 | |
| ### Custom Decision Types
 | |
| 
 | |
| ```go
 | |
| // Define custom decision type
 | |
| type DataScienceDecision struct {
 | |
|     decisions.TaskDecision
 | |
|     ModelName        string            `json:"model_name"`
 | |
|     TrainingAccuracy float64           `json:"training_accuracy"`
 | |
|     DatasetSize      int               `json:"dataset_size"`
 | |
|     HyperParams      map[string]float64 `json:"hyperparameters"`
 | |
| }
 | |
| 
 | |
| // Publish custom decision
 | |
| customDecision := &DataScienceDecision{
 | |
|     TaskDecision: decisions.TaskDecision{
 | |
|         Task:     "train_sentiment_model",
 | |
|         Decision: "Trained BERT model for sentiment analysis",
 | |
|         Success:  true,
 | |
|     },
 | |
|     ModelName:        "bert-base-sentiment",
 | |
|     TrainingAccuracy: 0.94,
 | |
|     DatasetSize:      50000,
 | |
|     HyperParams: map[string]float64{
 | |
|         "learning_rate": 0.001,
 | |
|         "batch_size":    32,
 | |
|         "epochs":        10,
 | |
|     },
 | |
| }
 | |
| 
 | |
| err = decisionClient.PublishCustom(ctx, "data_science", customDecision)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to publish custom decision: %w", err)
 | |
| }
 | |
| ```
 | |
| 
 | |
| ### Decision Streaming
 | |
| 
 | |
| ```go
 | |
| // Stream decisions in real-time
 | |
| stream, err := decisionClient.StreamDecisions(ctx, decisions.StreamRequest{
 | |
|     Role:        "backend_developer",
 | |
|     ContentType: "decision",
 | |
| })
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to start stream: %w", err)
 | |
| }
 | |
| defer stream.Close()
 | |
| 
 | |
| for {
 | |
|     select {
 | |
|     case decision := <-stream.Decisions():
 | |
|         fmt.Printf("New decision: %s\n", decision.Address)
 | |
|         processDecision(decision)
 | |
|         
 | |
|     case err := <-stream.Errors():
 | |
|         log.Printf("Stream error: %v", err)
 | |
|         
 | |
|     case <-ctx.Done():
 | |
|         return ctx.Err()
 | |
|     }
 | |
| }
 | |
| ```
 | |
| 
 | |
| **Cross-Reference**: Decision implementation in `pkg/ucxl/` and `sdk/decisions/`
 | |
| 
 | |
| ## Election SDK
 | |
| 
 | |
| The election SDK provides access to admin election and consensus operations.
 | |
| 
 | |
| ### Election Management
 | |
| 
 | |
| ```go
 | |
| import "github.com/anthonyrawlins/bzzz/sdk/elections"
 | |
| 
 | |
| // Create election client
 | |
| electionClient := elections.NewClient(client)
 | |
| 
 | |
| // Get current election status
 | |
| status, err := electionClient.GetStatus(ctx)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to get election status: %w", err)
 | |
| }
 | |
| 
 | |
| fmt.Printf("Current admin: %s\n", status.CurrentAdmin)
 | |
| fmt.Printf("Election active: %t\n", status.IsElectionActive)
 | |
| fmt.Printf("Last heartbeat: %s\n", status.LastHeartbeat.Format(time.RFC3339))
 | |
| 
 | |
| // Monitor election events
 | |
| events, err := electionClient.MonitorElections(ctx)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to monitor elections: %w", err)
 | |
| }
 | |
| defer events.Close()
 | |
| 
 | |
| for {
 | |
|     select {
 | |
|     case event := <-events.Events():
 | |
|         switch event.Type {
 | |
|         case elections.ElectionStarted:
 | |
|             fmt.Printf("Election started: %s\n", event.ElectionID)
 | |
|             
 | |
|         case elections.CandidateProposed:
 | |
|             fmt.Printf("New candidate: %s (score: %.1f)\n", 
 | |
|                 event.Candidate.NodeID, event.Candidate.Score)
 | |
|                 
 | |
|         case elections.ElectionCompleted:
 | |
|             fmt.Printf("Election completed. Winner: %s\n", event.Winner)
 | |
|             
 | |
|         case elections.AdminHeartbeat:
 | |
|             fmt.Printf("Admin heartbeat from: %s\n", event.AdminID)
 | |
|         }
 | |
|         
 | |
|     case <-ctx.Done():
 | |
|         return ctx.Err()
 | |
|     }
 | |
| }
 | |
| ```
 | |
| 
 | |
| ### Admin Operations
 | |
| 
 | |
| ```go
 | |
| // Admin-only operations
 | |
| if client.IsAdmin() {
 | |
|     // Trigger manual election
 | |
|     election, err := electionClient.TriggerElection(ctx, elections.TriggerRequest{
 | |
|         Reason: "manual_trigger",
 | |
|         Force:  false,
 | |
|     })
 | |
|     if err != nil {
 | |
|         return fmt.Errorf("failed to trigger election: %w", err)
 | |
|     }
 | |
|     
 | |
|     fmt.Printf("Election %s started with %d candidates\n", 
 | |
|         election.ElectionID, len(election.Candidates))
 | |
|     
 | |
|     // Get admin key shares information
 | |
|     shares, err := electionClient.GetKeyShares(ctx)
 | |
|     if err != nil {
 | |
|         return fmt.Errorf("failed to get key shares: %w", err)
 | |
|     }
 | |
|     
 | |
|     fmt.Printf("Key shares: %d/%d distributed\n", 
 | |
|         len(shares.DistributedShares), shares.TotalShares)
 | |
|     fmt.Printf("Reconstruction possible: %t\n", shares.ReconstructionPossible)
 | |
| }
 | |
| ```
 | |
| 
 | |
| ### Consensus Operations
 | |
| 
 | |
| ```go
 | |
| // Participate in consensus (for eligible nodes)
 | |
| if status.CanParticipate {
 | |
|     // Propose candidacy
 | |
|     err = electionClient.ProposeCandidate(ctx, elections.CandidateProposal{
 | |
|         Capabilities: []string{"high_uptime", "master_authority"},
 | |
|         Resources: elections.NodeResources{
 | |
|             CPU:    0.2,  // 20% CPU usage
 | |
|             Memory: 0.15, // 15% memory usage  
 | |
|             Disk:   0.45, // 45% disk usage
 | |
|         },
 | |
|     })
 | |
|     if err != nil {
 | |
|         return fmt.Errorf("failed to propose candidacy: %w", err)
 | |
|     }
 | |
|     
 | |
|     // Vote in election (automatic based on scoring)
 | |
|     vote, err := electionClient.CastVote(ctx, elections.VoteRequest{
 | |
|         ElectionID:   status.CurrentElection,
 | |
|         CandidateID:  "QmBestCandidate",
 | |
|         VoteValue:    true,
 | |
|     })
 | |
|     if err != nil {
 | |
|         return fmt.Errorf("failed to cast vote: %w", err)
 | |
|     }
 | |
|     
 | |
|     fmt.Printf("Vote cast: %t\n", vote.Recorded)
 | |
| }
 | |
| ```
 | |
| 
 | |
| **Cross-Reference**: Election implementation in `pkg/election/` and `sdk/elections/`
 | |
| 
 | |
| ## Configuration SDK
 | |
| 
 | |
| The configuration SDK provides programmatic access to BZZZ configuration management.
 | |
| 
 | |
| ### Configuration Management
 | |
| 
 | |
| ```go
 | |
| import "github.com/anthonyrawlins/bzzz/sdk/config"
 | |
| 
 | |
| // Create config client
 | |
| configClient := config.NewClient(client)
 | |
| 
 | |
| // Get current configuration
 | |
| cfg, err := configClient.GetConfig(ctx)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to get config: %w", err)
 | |
| }
 | |
| 
 | |
| fmt.Printf("Node ID: %s\n", cfg.NodeID)
 | |
| fmt.Printf("Role: %s\n", cfg.Agent.Role)
 | |
| fmt.Printf("Authority: %s\n", cfg.Agent.AuthorityLevel)
 | |
| 
 | |
| // Update agent configuration
 | |
| err = configClient.UpdateAgent(ctx, config.AgentUpdate{
 | |
|     Role:           "senior_software_architect",
 | |
|     Specialization: "microservices_architecture", 
 | |
|     Models:         []string{"gpt-4", "claude-3-opus"},
 | |
|     MaxTasks:       10,
 | |
| })
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to update agent config: %w", err)
 | |
| }
 | |
| 
 | |
| // Update security configuration (admin only)
 | |
| if client.IsAdmin() {
 | |
|     err = configClient.UpdateSecurity(ctx, config.SecurityUpdate{
 | |
|         AdminKeyShares: config.ShamirConfig{
 | |
|             Threshold:   3,
 | |
|             TotalShares: 5,
 | |
|         },
 | |
|         ElectionTimeout: 30 * time.Second,
 | |
|         HeartbeatInterval: 5 * time.Second,
 | |
|     })
 | |
|     if err != nil {
 | |
|         return fmt.Errorf("failed to update security config: %w", err)
 | |
|     }
 | |
| }
 | |
| ```
 | |
| 
 | |
| ### Role Management
 | |
| 
 | |
| ```go
 | |
| // Get available roles
 | |
| roles, err := configClient.GetRoles(ctx)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to get roles: %w", err)
 | |
| }
 | |
| 
 | |
| for name, role := range roles.Roles {
 | |
|     fmt.Printf("Role: %s\n", name)
 | |
|     fmt.Printf("  Authority: %s\n", role.AuthorityLevel)
 | |
|     fmt.Printf("  Can decrypt: %v\n", role.CanDecrypt)
 | |
|     fmt.Printf("  Model: %s\n", role.Model)
 | |
| }
 | |
| 
 | |
| // Create custom role
 | |
| err = configClient.CreateRole(ctx, config.RoleDefinition{
 | |
|     Name:           "data_scientist",
 | |
|     AuthorityLevel: "decision",
 | |
|     CanDecrypt:     []string{"data_scientist", "backend_developer", "observer"},
 | |
|     Model:          "ollama/llama3.1",
 | |
|     DecisionScope:  []string{"data", "analytics", "ml_models"},
 | |
|     SpecialFunctions: []string{"model_training", "data_analysis"},
 | |
| })
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to create role: %w", err)
 | |
| }
 | |
| 
 | |
| // Generate keys for role
 | |
| keys, err := configClient.GenerateRoleKeys(ctx, "data_scientist")
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to generate role keys: %w", err)
 | |
| }
 | |
| 
 | |
| fmt.Printf("Generated keys for data_scientist role\n")
 | |
| fmt.Printf("Public key: %s\n", keys.PublicKey)
 | |
| // Store keys.PrivateKey securely
 | |
| ```
 | |
| 
 | |
| ### Configuration Validation
 | |
| 
 | |
| ```go
 | |
| // Validate configuration
 | |
| validation, err := configClient.ValidateConfig(ctx, cfg)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to validate config: %w", err)
 | |
| }
 | |
| 
 | |
| if !validation.Valid {
 | |
|     fmt.Printf("Configuration validation failed:\n")
 | |
|     for _, error := range validation.Errors {
 | |
|         fmt.Printf("  - %s: %s\n", error.Field, error.Message)
 | |
|     }
 | |
|     return fmt.Errorf("invalid configuration")
 | |
| }
 | |
| 
 | |
| // Get configuration schema
 | |
| schema, err := configClient.GetSchema(ctx)
 | |
| if err != nil {
 | |
|     return fmt.Errorf("failed to get schema: %w", err)
 | |
| }
 | |
| 
 | |
| // Use schema for validation in external tools
 | |
| fmt.Printf("Schema version: %s\n", schema.Version)
 | |
| fmt.Printf("Required fields: %v\n", schema.RequiredFields)
 | |
| ```
 | |
| 
 | |
| **Cross-Reference**: Configuration implementation in `pkg/config/` and `sdk/config/`
 | |
| 
 | |
| ## Examples
 | |
| 
 | |
| ### Complete Agent Implementation
 | |
| 
 | |
| ```go
 | |
| package main
 | |
| 
 | |
| import (
 | |
|     "context"
 | |
|     "fmt"
 | |
|     "log"
 | |
|     "os"
 | |
|     "os/signal"
 | |
|     "syscall"
 | |
|     "time"
 | |
|     
 | |
|     "github.com/anthonyrawlins/bzzz/sdk/bzzz"
 | |
|     "github.com/anthonyrawlins/bzzz/sdk/decisions"
 | |
|     "github.com/anthonyrawlins/bzzz/sdk/crypto"
 | |
| )
 | |
| 
 | |
| type CustomAgent struct {
 | |
|     client    *bzzz.Client
 | |
|     decisions *decisions.Client
 | |
|     crypto    *crypto.Client
 | |
|     shutdown  chan os.Signal
 | |
| }
 | |
| 
 | |
| func NewCustomAgent(endpoint, role string) (*CustomAgent, error) {
 | |
|     // Create BZZZ client
 | |
|     client, err := bzzz.NewClient(bzzz.Config{
 | |
|         Endpoint: endpoint,
 | |
|         Role:     role,
 | |
|         Timeout:  30 * time.Second,
 | |
|     })
 | |
|     if err != nil {
 | |
|         return nil, fmt.Errorf("failed to create client: %w", err)
 | |
|     }
 | |
|     
 | |
|     // Create specialized clients
 | |
|     decisionsClient := decisions.NewClient(client)
 | |
|     cryptoClient := crypto.NewClient(client)
 | |
|     
 | |
|     agent := &CustomAgent{
 | |
|         client:    client,
 | |
|         decisions: decisionsClient,
 | |
|         crypto:    cryptoClient,
 | |
|         shutdown:  make(chan os.Signal, 1),
 | |
|     }
 | |
|     
 | |
|     signal.Notify(agent.shutdown, os.Interrupt, syscall.SIGTERM)
 | |
|     
 | |
|     return agent, nil
 | |
| }
 | |
| 
 | |
| func (a *CustomAgent) Run(ctx context.Context) error {
 | |
|     log.Printf("Starting custom BZZZ agent...")
 | |
|     
 | |
|     // Get initial status
 | |
|     status, err := a.client.GetStatus(ctx)
 | |
|     if err != nil {
 | |
|         return fmt.Errorf("failed to get status: %w", err)
 | |
|     }
 | |
|     
 | |
|     log.Printf("Connected as %s (%s)", status.AgentID, status.Role)
 | |
|     
 | |
|     // Start event monitoring
 | |
|     events, err := a.client.SubscribeEvents(ctx)
 | |
|     if err != nil {
 | |
|         return fmt.Errorf("failed to subscribe to events: %w", err)
 | |
|     }
 | |
|     defer events.Close()
 | |
|     
 | |
|     // Start decision monitoring
 | |
|     decisions, err := a.decisions.StreamDecisions(ctx, decisions.StreamRequest{
 | |
|         Role: status.Role,
 | |
|     })
 | |
|     if err != nil {
 | |
|         return fmt.Errorf("failed to stream decisions: %w", err)
 | |
|     }
 | |
|     defer decisions.Close()
 | |
|     
 | |
|     // Start task processing
 | |
|     go a.processTask(ctx)
 | |
|     
 | |
|     // Main event loop
 | |
|     for {
 | |
|         select {
 | |
|         case event := <-events.Events():
 | |
|             a.handleEvent(event)
 | |
|             
 | |
|         case decision := <-decisions.Decisions():
 | |
|             a.handleDecision(decision)
 | |
|             
 | |
|         case <-a.shutdown:
 | |
|             log.Printf("Shutting down agent...")
 | |
|             return nil
 | |
|             
 | |
|         case <-ctx.Done():
 | |
|             return ctx.Err()
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| func (a *CustomAgent) handleEvent(event bzzz.Event) {
 | |
|     switch event.Type {
 | |
|     case "admin_changed":
 | |
|         log.Printf("Admin changed: %s -> %s", 
 | |
|             event.Data["old_admin"], event.Data["new_admin"])
 | |
|             
 | |
|     case "peer_connected":
 | |
|         log.Printf("Peer connected: %s (%s)", 
 | |
|             event.Data["agent_id"], event.Data["role"])
 | |
|             
 | |
|     default:
 | |
|         log.Printf("Received event: %s", event.Type)
 | |
|     }
 | |
| }
 | |
| 
 | |
| func (a *CustomAgent) handleDecision(decision decisions.TaskDecision) {
 | |
|     log.Printf("New decision: %s - %s", decision.Task, decision.Decision)
 | |
|     
 | |
|     // Process decision based on your logic
 | |
|     if decision.Success && len(decision.FilesModified) > 0 {
 | |
|         log.Printf("Successful task with %d files modified", len(decision.FilesModified))
 | |
|         // Trigger related tasks or analysis
 | |
|     }
 | |
| }
 | |
| 
 | |
| func (a *CustomAgent) processTask(ctx context.Context) {
 | |
|     // Simulate task processing
 | |
|     ticker := time.NewTicker(60 * time.Second)
 | |
|     defer ticker.Stop()
 | |
|     
 | |
|     taskCounter := 0
 | |
|     
 | |
|     for {
 | |
|         select {
 | |
|         case <-ticker.C:
 | |
|             taskCounter++
 | |
|             
 | |
|             // Simulate completing a task
 | |
|             err := a.decisions.PublishCode(ctx, decisions.CodeDecision{
 | |
|                 Task:     fmt.Sprintf("automated_task_%d", taskCounter),
 | |
|                 Decision: "Completed automated code analysis task",
 | |
|                 FilesModified: []string{
 | |
|                     fmt.Sprintf("analysis/task_%d.go", taskCounter),
 | |
|                 },
 | |
|                 LinesChanged: 50 + taskCounter*10,
 | |
|                 TestResults: &decisions.TestResults{
 | |
|                     Passed:   5,
 | |
|                     Failed:   0,
 | |
|                     Coverage: 85.0 + float64(taskCounter),
 | |
|                 },
 | |
|             })
 | |
|             
 | |
|             if err != nil {
 | |
|                 log.Printf("Failed to publish task completion: %v", err)
 | |
|             } else {
 | |
|                 log.Printf("Published completion for task %d", taskCounter)
 | |
|             }
 | |
|             
 | |
|         case <-ctx.Done():
 | |
|             return
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| func main() {
 | |
|     agent, err := NewCustomAgent("http://localhost:8080", "backend_developer")
 | |
|     if err != nil {
 | |
|         log.Fatal(err)
 | |
|     }
 | |
|     defer agent.client.Close()
 | |
|     
 | |
|     ctx := context.Background()
 | |
|     if err := agent.Run(ctx); err != nil {
 | |
|         log.Fatal(err)
 | |
|     }
 | |
| }
 | |
| ```
 | |
| 
 | |
| ### Data Analysis Tool
 | |
| 
 | |
| ```go
 | |
| package main
 | |
| 
 | |
| import (
 | |
|     "context"
 | |
|     "fmt"
 | |
|     "time"
 | |
|     
 | |
|     "github.com/anthonyrawlins/bzzz/sdk/bzzz"
 | |
|     "github.com/anthonyrawlins/bzzz/sdk/decisions"
 | |
| )
 | |
| 
 | |
| func analyzeDecisions() error {
 | |
|     // Connect to BZZZ
 | |
|     client, err := bzzz.NewClient(bzzz.Config{
 | |
|         Endpoint: "http://localhost:8080",
 | |
|         Role:     "observer", // Read-only access
 | |
|     })
 | |
|     if err != nil {
 | |
|         return err
 | |
|     }
 | |
|     defer client.Close()
 | |
|     
 | |
|     decisionsClient := decisions.NewClient(client)
 | |
|     
 | |
|     // Query last 30 days of decisions
 | |
|     since := time.Now().Add(-30 * 24 * time.Hour)
 | |
|     recent, err := decisionsClient.QueryRecent(context.Background(), decisions.QueryRequest{
 | |
|         Since: since,
 | |
|         Limit: 1000,
 | |
|     })
 | |
|     if err != nil {
 | |
|         return err
 | |
|     }
 | |
|     
 | |
|     // Analyze decision patterns
 | |
|     roleStats := make(map[string]int)
 | |
|     projectStats := make(map[string]int)
 | |
|     successRate := 0
 | |
|     totalDecisions := len(recent.Decisions)
 | |
|     
 | |
|     for _, decision := range recent.Decisions {
 | |
|         // Get full decision content
 | |
|         content, err := decisionsClient.GetContent(context.Background(), decision.Address)
 | |
|         if err != nil {
 | |
|             continue // Skip if we can't decrypt
 | |
|         }
 | |
|         
 | |
|         roleStats[content.Role]++
 | |
|         projectStats[content.Project]++
 | |
|         
 | |
|         if content.Success {
 | |
|             successRate++
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     // Print analysis
 | |
|     fmt.Printf("Decision Analysis (Last 30 Days)\n")
 | |
|     fmt.Printf("================================\n")
 | |
|     fmt.Printf("Total decisions: %d\n", totalDecisions)
 | |
|     fmt.Printf("Success rate: %.1f%%\n", float64(successRate)/float64(totalDecisions)*100)
 | |
|     
 | |
|     fmt.Printf("\nDecisions by Role:\n")
 | |
|     for role, count := range roleStats {
 | |
|         fmt.Printf("  %s: %d\n", role, count)
 | |
|     }
 | |
|     
 | |
|     fmt.Printf("\nDecisions by Project:\n")
 | |
|     for project, count := range projectStats {
 | |
|         fmt.Printf("  %s: %d\n", project, count)
 | |
|     }
 | |
|     
 | |
|     return nil
 | |
| }
 | |
| ```
 | |
| 
 | |
| ### Monitoring Dashboard
 | |
| 
 | |
| ```go
 | |
| package main
 | |
| 
 | |
| import (
 | |
|     "context"
 | |
|     "encoding/json"
 | |
|     "fmt"
 | |
|     "html/template"
 | |
|     "net/http"
 | |
|     "time"
 | |
|     
 | |
|     "github.com/anthonyrawlins/bzzz/sdk/bzzz"
 | |
|     "github.com/anthonyrawlins/bzzz/sdk/dht"
 | |
|     "github.com/anthonyrawlins/bzzz/sdk/elections"
 | |
| )
 | |
| 
 | |
| type Dashboard struct {
 | |
|     client    *bzzz.Client
 | |
|     dht       *dht.Client
 | |
|     elections *elections.Client
 | |
| }
 | |
| 
 | |
| func NewDashboard(bzzzEndpoint string) (*Dashboard, error) {
 | |
|     client, err := bzzz.NewClient(bzzz.Config{
 | |
|         Endpoint: bzzzEndpoint,
 | |
|         Role:     "observer",
 | |
|     })
 | |
|     if err != nil {
 | |
|         return nil, err
 | |
|     }
 | |
|     
 | |
|     return &Dashboard{
 | |
|         client:    client,
 | |
|         dht:       dht.NewClient(client),
 | |
|         elections: elections.NewClient(client),
 | |
|     }, nil
 | |
| }
 | |
| 
 | |
| func (d *Dashboard) GetMetrics(ctx context.Context) (map[string]interface{}, error) {
 | |
|     // Get node status
 | |
|     status, err := d.client.GetStatus(ctx)
 | |
|     if err != nil {
 | |
|         return nil, err
 | |
|     }
 | |
|     
 | |
|     // Get DHT metrics
 | |
|     dhtMetrics, err := d.dht.GetMetrics(ctx)
 | |
|     if err != nil {
 | |
|         return nil, err
 | |
|     }
 | |
|     
 | |
|     // Get election status
 | |
|     electionStatus, err := d.elections.GetStatus(ctx)
 | |
|     if err != nil {
 | |
|         return nil, err
 | |
|     }
 | |
|     
 | |
|     // Get peers
 | |
|     peers, err := d.client.GetPeers(ctx)
 | |
|     if err != nil {
 | |
|         return nil, err
 | |
|     }
 | |
|     
 | |
|     return map[string]interface{}{
 | |
|         "node":      status,
 | |
|         "dht":       dhtMetrics,
 | |
|         "elections": electionStatus,
 | |
|         "peers":     peers,
 | |
|         "timestamp": time.Now(),
 | |
|     }, nil
 | |
| }
 | |
| 
 | |
| func (d *Dashboard) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 | |
|     switch r.URL.Path {
 | |
|     case "/":
 | |
|         d.serveDashboard(w, r)
 | |
|     case "/api/metrics":
 | |
|         d.serveMetrics(w, r)
 | |
|     case "/api/events":
 | |
|         d.serveEventStream(w, r)
 | |
|     default:
 | |
|         http.NotFound(w, r)
 | |
|     }
 | |
| }
 | |
| 
 | |
| func (d *Dashboard) serveDashboard(w http.ResponseWriter, r *http.Request) {
 | |
|     tmpl := template.Must(template.New("dashboard").Parse(dashboardHTML))
 | |
|     tmpl.Execute(w, nil)
 | |
| }
 | |
| 
 | |
| func (d *Dashboard) serveMetrics(w http.ResponseWriter, r *http.Request) {
 | |
|     metrics, err := d.GetMetrics(r.Context())
 | |
|     if err != nil {
 | |
|         http.Error(w, err.Error(), http.StatusInternalServerError)
 | |
|         return
 | |
|     }
 | |
|     
 | |
|     w.Header().Set("Content-Type", "application/json")
 | |
|     json.NewEncoder(w).Encode(metrics)
 | |
| }
 | |
| 
 | |
| func (d *Dashboard) serveEventStream(w http.ResponseWriter, r *http.Request) {
 | |
|     // Set up SSE headers
 | |
|     w.Header().Set("Content-Type", "text/event-stream")
 | |
|     w.Header().Set("Cache-Control", "no-cache")
 | |
|     w.Header().Set("Connection", "keep-alive")
 | |
|     
 | |
|     // Subscribe to events
 | |
|     events, err := d.client.SubscribeEvents(r.Context())
 | |
|     if err != nil {
 | |
|         fmt.Fprintf(w, "data: {\"error\": \"%s\"}\n\n", err.Error())
 | |
|         return
 | |
|     }
 | |
|     defer events.Close()
 | |
|     
 | |
|     // Stream events
 | |
|     for {
 | |
|         select {
 | |
|         case event := <-events.Events():
 | |
|             data, _ := json.Marshal(event)
 | |
|             fmt.Fprintf(w, "data: %s\n\n", data)
 | |
|             if f, ok := w.(http.Flusher); ok {
 | |
|                 f.Flush()
 | |
|             }
 | |
|             
 | |
|         case <-r.Context().Done():
 | |
|             return
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| const dashboardHTML = `
 | |
| <!DOCTYPE html>
 | |
| <html>
 | |
| <head>
 | |
|     <title>BZZZ Dashboard</title>
 | |
|     <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
 | |
| </head>
 | |
| <body>
 | |
|     <h1>BZZZ Cluster Dashboard</h1>
 | |
|     
 | |
|     <div id="status"></div>
 | |
|     <div id="metrics"></div>
 | |
|     <div id="events"></div>
 | |
|     
 | |
|     <script>
 | |
|         // Fetch and display metrics
 | |
|         async function updateMetrics() {
 | |
|             const response = await fetch('/api/metrics');
 | |
|             const metrics = await response.json();
 | |
|             
 | |
|             document.getElementById('status').innerHTML = 
 | |
|                 '<h2>Node Status</h2>' +
 | |
|                 '<p>Node ID: ' + metrics.node.node_id + '</p>' +
 | |
|                 '<p>Role: ' + metrics.node.role + '</p>' +
 | |
|                 '<p>Admin: ' + metrics.elections.current_admin + '</p>';
 | |
|                 
 | |
|             document.getElementById('metrics').innerHTML = 
 | |
|                 '<h2>DHT Metrics</h2>' +
 | |
|                 '<p>Stored Items: ' + metrics.dht.stored_items + '</p>' +
 | |
|                 '<p>Cache Hit Rate: ' + (metrics.dht.cache_hit_rate * 100).toFixed(1) + '%</p>' +
 | |
|                 '<p>Connected Peers: ' + metrics.dht.connected_peers + '</p>';
 | |
|         }
 | |
|         
 | |
|         // Set up event stream
 | |
|         const eventSource = new EventSource('/api/events');
 | |
|         eventSource.onmessage = function(event) {
 | |
|             const data = JSON.parse(event.data);
 | |
|             const eventsDiv = document.getElementById('events');
 | |
|             eventsDiv.innerHTML = '<h2>Recent Events</h2>' + 
 | |
|                 '<p>' + data.type + ': ' + JSON.stringify(data.data) + '</p>' +
 | |
|                 eventsDiv.innerHTML;
 | |
|         };
 | |
|         
 | |
|         // Update metrics every 10 seconds
 | |
|         updateMetrics();
 | |
|         setInterval(updateMetrics, 10000);
 | |
|     </script>
 | |
| </body>
 | |
| </html>
 | |
| `
 | |
| 
 | |
| func main() {
 | |
|     dashboard, err := NewDashboard("http://localhost:8080")
 | |
|     if err != nil {
 | |
|         panic(err)
 | |
|     }
 | |
|     
 | |
|     http.Handle("/", dashboard)
 | |
|     
 | |
|     fmt.Println("Dashboard available at http://localhost:3000")
 | |
|     http.ListenAndServe(":3000", nil)
 | |
| }
 | |
| ```
 | |
| 
 | |
| ## Language Bindings
 | |
| 
 | |
| ### Python SDK
 | |
| 
 | |
| ```python
 | |
| # Install: pip install bzzz-sdk
 | |
| import asyncio
 | |
| from bzzz_sdk import BzzzClient, DecisionType
 | |
| 
 | |
| async def main():
 | |
|     # Create client
 | |
|     client = BzzzClient(
 | |
|         endpoint="http://localhost:8080",
 | |
|         role="backend_developer"
 | |
|     )
 | |
|     
 | |
|     # Get status
 | |
|     status = await client.get_status()
 | |
|     print(f"Connected as {status.agent_id} ({status.role})")
 | |
|     
 | |
|     # Publish decision
 | |
|     await client.decisions.publish_code(
 | |
|         task="implement_feature",
 | |
|         decision="Implemented new API endpoint",
 | |
|         files_modified=["api/handlers.py", "tests/test_api.py"],
 | |
|         lines_changed=120
 | |
|     )
 | |
|     
 | |
|     # Query decisions
 | |
|     decisions = await client.decisions.query_recent(
 | |
|         role="backend_developer",
 | |
|         limit=10
 | |
|     )
 | |
|     
 | |
|     for decision in decisions:
 | |
|         print(f"Decision: {decision.task} - {decision.success}")
 | |
|     
 | |
|     await client.close()
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     asyncio.run(main())
 | |
| ```
 | |
| 
 | |
| ### JavaScript/Node.js SDK
 | |
| 
 | |
| ```javascript
 | |
| // Install: npm install bzzz-sdk
 | |
| const { BzzzClient } = require('bzzz-sdk');
 | |
| 
 | |
| async function main() {
 | |
|     // Create client
 | |
|     const client = new BzzzClient({
 | |
|         endpoint: 'http://localhost:8080',
 | |
|         role: 'frontend_developer'
 | |
|     });
 | |
|     
 | |
|     // Get status
 | |
|     const status = await client.getStatus();
 | |
|     console.log(`Connected as ${status.agentId} (${status.role})`);
 | |
|     
 | |
|     // Subscribe to events
 | |
|     const events = client.subscribeEvents();
 | |
|     events.on('decision_published', (decision) => {
 | |
|         console.log(`New decision: ${decision.address}`);
 | |
|     });
 | |
|     
 | |
|     // Publish architectural decision
 | |
|     await client.decisions.publishArchitectural({
 | |
|         task: 'redesign_ui',
 | |
|         decision: 'Migrating to React with TypeScript',
 | |
|         rationale: 'Better type safety and developer experience',
 | |
|         alternatives: ['Vue.js', 'Angular', 'Svelte'],
 | |
|         nextSteps: ['Set up build pipeline', 'Migrate components']
 | |
|     });
 | |
|     
 | |
|     // Query decisions
 | |
|     const recentDecisions = await client.decisions.queryRecent({
 | |
|         role: 'frontend_developer',
 | |
|         project: 'user_interface',
 | |
|         limit: 5
 | |
|     });
 | |
|     
 | |
|     recentDecisions.forEach(decision => {
 | |
|         console.log(`Decision: ${decision.task} - ${decision.success}`);
 | |
|     });
 | |
| }
 | |
| 
 | |
| main().catch(console.error);
 | |
| ```
 | |
| 
 | |
| ### Rust SDK
 | |
| 
 | |
| ```rust
 | |
| // Cargo.toml: bzzz-sdk = "2.0"
 | |
| use bzzz_sdk::{BzzzClient, decisions::CodeDecision, crypto::AgeKeyPair};
 | |
| use tokio;
 | |
| 
 | |
| #[tokio::main]
 | |
| async fn main() -> Result<(), Box<dyn std::error::Error>> {
 | |
|     // Create client
 | |
|     let client = BzzzClient::new(bzzz_sdk::Config {
 | |
|         endpoint: "http://localhost:8080".to_string(),
 | |
|         role: "backend_developer".to_string(),
 | |
|         timeout: std::time::Duration::from_secs(30),
 | |
|         ..Default::default()
 | |
|     }).await?;
 | |
|     
 | |
|     // Get status
 | |
|     let status = client.get_status().await?;
 | |
|     println!("Connected as {} ({})", status.agent_id, status.role);
 | |
|     
 | |
|     // Generate Age keys
 | |
|     let keys = client.crypto().generate_keys().await?;
 | |
|     println!("Generated Age key pair");
 | |
|     
 | |
|     // Publish code decision
 | |
|     client.decisions().publish_code(CodeDecision {
 | |
|         task: "optimize_performance".to_string(),
 | |
|         decision: "Implemented async processing with Tokio".to_string(),
 | |
|         files_modified: vec![
 | |
|             "src/async_handler.rs".to_string(),
 | |
|             "src/main.rs".to_string(),
 | |
|         ],
 | |
|         lines_changed: 180,
 | |
|         test_results: Some(bzzz_sdk::decisions::TestResults {
 | |
|             passed: 25,
 | |
|             failed: 0,
 | |
|             coverage: 92.5,
 | |
|             ..Default::default()
 | |
|         }),
 | |
|         dependencies: vec![
 | |
|             "tokio".to_string(),
 | |
|             "futures".to_string(),
 | |
|         ],
 | |
|         ..Default::default()
 | |
|     }).await?;
 | |
|     
 | |
|     println!("Published code decision");
 | |
|     
 | |
|     Ok(())
 | |
| }
 | |
| ```
 | |
| 
 | |
| ---
 | |
| 
 | |
| ## Cross-References
 | |
| 
 | |
| - **Core Implementation**: `pkg/` packages in main codebase
 | |
| - **HTTP API**: [API_REFERENCE.md](API_REFERENCE.md) - REST API documentation
 | |
| - **User Guide**: [USER_MANUAL.md](USER_MANUAL.md) - End-user documentation
 | |
| - **Developer Guide**: [DEVELOPER.md](DEVELOPER.md) - Development documentation
 | |
| - **Examples**: `examples/sdk/` directory in repository
 | |
| 
 | |
| **BZZZ SDK v2.0** - Complete Software Development Kit for Phase 2B unified architecture with Age encryption and DHT storage. |