chore: align slurp config and scaffolding
This commit is contained in:
@@ -10,18 +10,18 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"chorus/pkg/dht"
|
||||
"chorus/pkg/crypto"
|
||||
"chorus/pkg/election"
|
||||
"chorus/pkg/ucxl"
|
||||
"chorus/pkg/config"
|
||||
"chorus/pkg/crypto"
|
||||
"chorus/pkg/dht"
|
||||
"chorus/pkg/election"
|
||||
slurpContext "chorus/pkg/slurp/context"
|
||||
"chorus/pkg/ucxl"
|
||||
)
|
||||
|
||||
// DHTContextDistributor implements ContextDistributor using CHORUS DHT infrastructure
|
||||
type DHTContextDistributor struct {
|
||||
mu sync.RWMutex
|
||||
dht *dht.DHT
|
||||
dht dht.DHT
|
||||
roleCrypto *crypto.RoleCrypto
|
||||
election election.Election
|
||||
config *config.Config
|
||||
@@ -37,7 +37,7 @@ type DHTContextDistributor struct {
|
||||
|
||||
// NewDHTContextDistributor creates a new DHT-based context distributor
|
||||
func NewDHTContextDistributor(
|
||||
dht *dht.DHT,
|
||||
dht dht.DHT,
|
||||
roleCrypto *crypto.RoleCrypto,
|
||||
election election.Election,
|
||||
config *config.Config,
|
||||
@@ -147,36 +147,43 @@ func (d *DHTContextDistributor) DistributeContext(ctx context.Context, node *slu
|
||||
return d.recordError(fmt.Sprintf("failed to get vector clock: %v", err))
|
||||
}
|
||||
|
||||
// Encrypt context for roles
|
||||
encryptedData, err := d.roleCrypto.EncryptContextForRoles(node, roles, []string{})
|
||||
// Prepare context payload for role encryption
|
||||
rawContext, err := json.Marshal(node)
|
||||
if err != nil {
|
||||
return d.recordError(fmt.Sprintf("failed to encrypt context: %v", err))
|
||||
return d.recordError(fmt.Sprintf("failed to marshal context: %v", err))
|
||||
}
|
||||
|
||||
// Create distribution metadata
|
||||
// Create distribution metadata (checksum calculated per-role below)
|
||||
metadata := &DistributionMetadata{
|
||||
Address: node.UCXLAddress,
|
||||
Roles: roles,
|
||||
Version: 1,
|
||||
VectorClock: clock,
|
||||
DistributedBy: d.config.Agent.ID,
|
||||
DistributedAt: time.Now(),
|
||||
Roles: roles,
|
||||
Version: 1,
|
||||
VectorClock: clock,
|
||||
DistributedBy: d.config.Agent.ID,
|
||||
DistributedAt: time.Now(),
|
||||
ReplicationFactor: d.getReplicationFactor(),
|
||||
Checksum: d.calculateChecksum(encryptedData),
|
||||
}
|
||||
|
||||
// Store encrypted data in DHT for each role
|
||||
for _, role := range roles {
|
||||
key := d.keyGenerator.GenerateContextKey(node.UCXLAddress.String(), role)
|
||||
|
||||
|
||||
cipher, fingerprint, err := d.roleCrypto.EncryptForRole(rawContext, role)
|
||||
if err != nil {
|
||||
return d.recordError(fmt.Sprintf("failed to encrypt context for role %s: %v", role, err))
|
||||
}
|
||||
|
||||
// Create role-specific storage package
|
||||
storagePackage := &ContextStoragePackage{
|
||||
EncryptedData: encryptedData,
|
||||
Metadata: metadata,
|
||||
Role: role,
|
||||
StoredAt: time.Now(),
|
||||
EncryptedData: cipher,
|
||||
KeyFingerprint: fingerprint,
|
||||
Metadata: metadata,
|
||||
Role: role,
|
||||
StoredAt: time.Now(),
|
||||
}
|
||||
|
||||
metadata.Checksum = d.calculateChecksum(cipher)
|
||||
|
||||
// Serialize for storage
|
||||
storageBytes, err := json.Marshal(storagePackage)
|
||||
if err != nil {
|
||||
@@ -252,25 +259,30 @@ func (d *DHTContextDistributor) RetrieveContext(ctx context.Context, address ucx
|
||||
}
|
||||
|
||||
// Decrypt context for role
|
||||
contextNode, err := d.roleCrypto.DecryptContextForRole(storagePackage.EncryptedData, role)
|
||||
plain, err := d.roleCrypto.DecryptForRole(storagePackage.EncryptedData, role, storagePackage.KeyFingerprint)
|
||||
if err != nil {
|
||||
return nil, d.recordRetrievalError(fmt.Sprintf("failed to decrypt context: %v", err))
|
||||
}
|
||||
|
||||
var contextNode slurpContext.ContextNode
|
||||
if err := json.Unmarshal(plain, &contextNode); err != nil {
|
||||
return nil, d.recordRetrievalError(fmt.Sprintf("failed to decode context: %v", err))
|
||||
}
|
||||
|
||||
// Convert to resolved context
|
||||
resolvedContext := &slurpContext.ResolvedContext{
|
||||
UCXLAddress: contextNode.UCXLAddress,
|
||||
Summary: contextNode.Summary,
|
||||
Purpose: contextNode.Purpose,
|
||||
Technologies: contextNode.Technologies,
|
||||
Tags: contextNode.Tags,
|
||||
Insights: contextNode.Insights,
|
||||
ContextSourcePath: contextNode.Path,
|
||||
InheritanceChain: []string{contextNode.Path},
|
||||
ResolutionConfidence: contextNode.RAGConfidence,
|
||||
BoundedDepth: 1,
|
||||
GlobalContextsApplied: false,
|
||||
ResolvedAt: time.Now(),
|
||||
UCXLAddress: contextNode.UCXLAddress,
|
||||
Summary: contextNode.Summary,
|
||||
Purpose: contextNode.Purpose,
|
||||
Technologies: contextNode.Technologies,
|
||||
Tags: contextNode.Tags,
|
||||
Insights: contextNode.Insights,
|
||||
ContextSourcePath: contextNode.Path,
|
||||
InheritanceChain: []string{contextNode.Path},
|
||||
ResolutionConfidence: contextNode.RAGConfidence,
|
||||
BoundedDepth: 1,
|
||||
GlobalContextsApplied: false,
|
||||
ResolvedAt: time.Now(),
|
||||
}
|
||||
|
||||
// Update statistics
|
||||
@@ -304,15 +316,15 @@ func (d *DHTContextDistributor) UpdateContext(ctx context.Context, node *slurpCo
|
||||
|
||||
// Convert existing resolved context back to context node for comparison
|
||||
existingNode := &slurpContext.ContextNode{
|
||||
Path: existingContext.ContextSourcePath,
|
||||
UCXLAddress: existingContext.UCXLAddress,
|
||||
Summary: existingContext.Summary,
|
||||
Purpose: existingContext.Purpose,
|
||||
Technologies: existingContext.Technologies,
|
||||
Tags: existingContext.Tags,
|
||||
Insights: existingContext.Insights,
|
||||
RAGConfidence: existingContext.ResolutionConfidence,
|
||||
GeneratedAt: existingContext.ResolvedAt,
|
||||
Path: existingContext.ContextSourcePath,
|
||||
UCXLAddress: existingContext.UCXLAddress,
|
||||
Summary: existingContext.Summary,
|
||||
Purpose: existingContext.Purpose,
|
||||
Technologies: existingContext.Technologies,
|
||||
Tags: existingContext.Tags,
|
||||
Insights: existingContext.Insights,
|
||||
RAGConfidence: existingContext.ResolutionConfidence,
|
||||
GeneratedAt: existingContext.ResolvedAt,
|
||||
}
|
||||
|
||||
// Use conflict resolver to handle the update
|
||||
@@ -357,7 +369,7 @@ func (d *DHTContextDistributor) DeleteContext(ctx context.Context, address ucxl.
|
||||
func (d *DHTContextDistributor) ListDistributedContexts(ctx context.Context, role string, criteria *DistributionCriteria) ([]*DistributedContextInfo, error) {
|
||||
// This is a simplified implementation
|
||||
// In production, we'd maintain proper indexes and filtering
|
||||
|
||||
|
||||
results := []*DistributedContextInfo{}
|
||||
limit := 100
|
||||
if criteria != nil && criteria.Limit > 0 {
|
||||
@@ -380,13 +392,13 @@ func (d *DHTContextDistributor) Sync(ctx context.Context) (*SyncResult, error) {
|
||||
}
|
||||
|
||||
result := &SyncResult{
|
||||
SyncedContexts: 0, // Would be populated in real implementation
|
||||
SyncedContexts: 0, // Would be populated in real implementation
|
||||
ConflictsResolved: 0,
|
||||
Errors: []string{},
|
||||
SyncTime: time.Since(start),
|
||||
PeersContacted: len(d.dht.GetConnectedPeers()),
|
||||
DataTransferred: 0,
|
||||
SyncedAt: time.Now(),
|
||||
Errors: []string{},
|
||||
SyncTime: time.Since(start),
|
||||
PeersContacted: len(d.dht.GetConnectedPeers()),
|
||||
DataTransferred: 0,
|
||||
SyncedAt: time.Now(),
|
||||
}
|
||||
|
||||
return result, nil
|
||||
@@ -453,28 +465,13 @@ func (d *DHTContextDistributor) calculateChecksum(data interface{}) string {
|
||||
return hex.EncodeToString(hash[:])
|
||||
}
|
||||
|
||||
// Ensure DHT is bootstrapped before operations
|
||||
func (d *DHTContextDistributor) ensureDHTReady() error {
|
||||
if !d.dht.IsBootstrapped() {
|
||||
return fmt.Errorf("DHT not bootstrapped")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start starts the distribution service
|
||||
func (d *DHTContextDistributor) Start(ctx context.Context) error {
|
||||
// Bootstrap DHT if not already done
|
||||
if !d.dht.IsBootstrapped() {
|
||||
if err := d.dht.Bootstrap(); err != nil {
|
||||
return fmt.Errorf("failed to bootstrap DHT: %w", err)
|
||||
if d.gossipProtocol != nil {
|
||||
if err := d.gossipProtocol.StartGossip(ctx); err != nil {
|
||||
return fmt.Errorf("failed to start gossip protocol: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Start gossip protocol
|
||||
if err := d.gossipProtocol.StartGossip(ctx); err != nil {
|
||||
return fmt.Errorf("failed to start gossip protocol: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -488,22 +485,23 @@ func (d *DHTContextDistributor) Stop(ctx context.Context) error {
|
||||
|
||||
// ContextStoragePackage represents a complete package for DHT storage
|
||||
type ContextStoragePackage struct {
|
||||
EncryptedData *crypto.EncryptedContextData `json:"encrypted_data"`
|
||||
Metadata *DistributionMetadata `json:"metadata"`
|
||||
Role string `json:"role"`
|
||||
StoredAt time.Time `json:"stored_at"`
|
||||
EncryptedData []byte `json:"encrypted_data"`
|
||||
KeyFingerprint string `json:"key_fingerprint,omitempty"`
|
||||
Metadata *DistributionMetadata `json:"metadata"`
|
||||
Role string `json:"role"`
|
||||
StoredAt time.Time `json:"stored_at"`
|
||||
}
|
||||
|
||||
// DistributionMetadata contains metadata for distributed context
|
||||
type DistributionMetadata struct {
|
||||
Address ucxl.Address `json:"address"`
|
||||
Roles []string `json:"roles"`
|
||||
Version int64 `json:"version"`
|
||||
VectorClock *VectorClock `json:"vector_clock"`
|
||||
DistributedBy string `json:"distributed_by"`
|
||||
DistributedAt time.Time `json:"distributed_at"`
|
||||
ReplicationFactor int `json:"replication_factor"`
|
||||
Checksum string `json:"checksum"`
|
||||
Address ucxl.Address `json:"address"`
|
||||
Roles []string `json:"roles"`
|
||||
Version int64 `json:"version"`
|
||||
VectorClock *VectorClock `json:"vector_clock"`
|
||||
DistributedBy string `json:"distributed_by"`
|
||||
DistributedAt time.Time `json:"distributed_at"`
|
||||
ReplicationFactor int `json:"replication_factor"`
|
||||
Checksum string `json:"checksum"`
|
||||
}
|
||||
|
||||
// DHTKeyGenerator implements KeyGenerator interface
|
||||
@@ -532,65 +530,124 @@ func (kg *DHTKeyGenerator) GenerateReplicationKey(address string) string {
|
||||
// Component constructors - these would be implemented in separate files
|
||||
|
||||
// NewReplicationManager creates a new replication manager
|
||||
func NewReplicationManager(dht *dht.DHT, config *config.Config) (ReplicationManager, error) {
|
||||
// Placeholder implementation
|
||||
return &ReplicationManagerImpl{}, nil
|
||||
func NewReplicationManager(dht dht.DHT, config *config.Config) (ReplicationManager, error) {
|
||||
impl, err := NewReplicationManagerImpl(dht, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return impl, nil
|
||||
}
|
||||
|
||||
// NewConflictResolver creates a new conflict resolver
|
||||
func NewConflictResolver(dht *dht.DHT, config *config.Config) (ConflictResolver, error) {
|
||||
// Placeholder implementation
|
||||
func NewConflictResolver(dht dht.DHT, config *config.Config) (ConflictResolver, error) {
|
||||
// Placeholder implementation until full resolver is wired
|
||||
return &ConflictResolverImpl{}, nil
|
||||
}
|
||||
|
||||
// NewGossipProtocol creates a new gossip protocol
|
||||
func NewGossipProtocol(dht *dht.DHT, config *config.Config) (GossipProtocol, error) {
|
||||
// Placeholder implementation
|
||||
return &GossipProtocolImpl{}, nil
|
||||
func NewGossipProtocol(dht dht.DHT, config *config.Config) (GossipProtocol, error) {
|
||||
impl, err := NewGossipProtocolImpl(dht, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return impl, nil
|
||||
}
|
||||
|
||||
// NewNetworkManager creates a new network manager
|
||||
func NewNetworkManager(dht *dht.DHT, config *config.Config) (NetworkManager, error) {
|
||||
// Placeholder implementation
|
||||
return &NetworkManagerImpl{}, nil
|
||||
func NewNetworkManager(dht dht.DHT, config *config.Config) (NetworkManager, error) {
|
||||
impl, err := NewNetworkManagerImpl(dht, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return impl, nil
|
||||
}
|
||||
|
||||
// NewVectorClockManager creates a new vector clock manager
|
||||
func NewVectorClockManager(dht *dht.DHT, nodeID string) (VectorClockManager, error) {
|
||||
// Placeholder implementation
|
||||
return &VectorClockManagerImpl{}, nil
|
||||
func NewVectorClockManager(dht dht.DHT, nodeID string) (VectorClockManager, error) {
|
||||
return &defaultVectorClockManager{
|
||||
clocks: make(map[string]*VectorClock),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Placeholder structs for components - these would be properly implemented
|
||||
|
||||
type ReplicationManagerImpl struct{}
|
||||
func (rm *ReplicationManagerImpl) EnsureReplication(ctx context.Context, address ucxl.Address, factor int) error { return nil }
|
||||
func (rm *ReplicationManagerImpl) GetReplicationStatus(ctx context.Context, address ucxl.Address) (*ReplicaHealth, error) {
|
||||
return &ReplicaHealth{}, nil
|
||||
}
|
||||
func (rm *ReplicationManagerImpl) SetReplicationFactor(factor int) error { return nil }
|
||||
|
||||
// ConflictResolverImpl is a temporary stub until the full resolver is implemented
|
||||
type ConflictResolverImpl struct{}
|
||||
|
||||
func (cr *ConflictResolverImpl) ResolveConflict(ctx context.Context, local, remote *slurpContext.ContextNode) (*ConflictResolution, error) {
|
||||
return &ConflictResolution{
|
||||
Address: local.UCXLAddress,
|
||||
Address: local.UCXLAddress,
|
||||
ResolutionType: ResolutionMerged,
|
||||
MergedContext: local,
|
||||
MergedContext: local,
|
||||
ResolutionTime: time.Millisecond,
|
||||
ResolvedAt: time.Now(),
|
||||
Confidence: 0.95,
|
||||
ResolvedAt: time.Now(),
|
||||
Confidence: 0.95,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type GossipProtocolImpl struct{}
|
||||
func (gp *GossipProtocolImpl) StartGossip(ctx context.Context) error { return nil }
|
||||
// defaultVectorClockManager provides a minimal vector clock store for SEC-SLURP scaffolding.
|
||||
type defaultVectorClockManager struct {
|
||||
mu sync.Mutex
|
||||
clocks map[string]*VectorClock
|
||||
}
|
||||
|
||||
type NetworkManagerImpl struct{}
|
||||
func (vcm *defaultVectorClockManager) GetClock(nodeID string) (*VectorClock, error) {
|
||||
vcm.mu.Lock()
|
||||
defer vcm.mu.Unlock()
|
||||
|
||||
type VectorClockManagerImpl struct{}
|
||||
func (vcm *VectorClockManagerImpl) GetClock(nodeID string) (*VectorClock, error) {
|
||||
return &VectorClock{
|
||||
Clock: map[string]int64{nodeID: time.Now().Unix()},
|
||||
if clock, ok := vcm.clocks[nodeID]; ok {
|
||||
return clock, nil
|
||||
}
|
||||
clock := &VectorClock{
|
||||
Clock: map[string]int64{nodeID: time.Now().Unix()},
|
||||
UpdatedAt: time.Now(),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
vcm.clocks[nodeID] = clock
|
||||
return clock, nil
|
||||
}
|
||||
|
||||
func (vcm *defaultVectorClockManager) UpdateClock(nodeID string, clock *VectorClock) error {
|
||||
vcm.mu.Lock()
|
||||
defer vcm.mu.Unlock()
|
||||
|
||||
vcm.clocks[nodeID] = clock
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vcm *defaultVectorClockManager) CompareClock(clock1, clock2 *VectorClock) ClockRelation {
|
||||
if clock1 == nil || clock2 == nil {
|
||||
return ClockConcurrent
|
||||
}
|
||||
if clock1.UpdatedAt.Before(clock2.UpdatedAt) {
|
||||
return ClockBefore
|
||||
}
|
||||
if clock1.UpdatedAt.After(clock2.UpdatedAt) {
|
||||
return ClockAfter
|
||||
}
|
||||
return ClockEqual
|
||||
}
|
||||
|
||||
func (vcm *defaultVectorClockManager) MergeClock(clocks []*VectorClock) *VectorClock {
|
||||
if len(clocks) == 0 {
|
||||
return &VectorClock{
|
||||
Clock: map[string]int64{},
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
}
|
||||
merged := &VectorClock{
|
||||
Clock: make(map[string]int64),
|
||||
UpdatedAt: clocks[0].UpdatedAt,
|
||||
}
|
||||
for _, clock := range clocks {
|
||||
if clock == nil {
|
||||
continue
|
||||
}
|
||||
if clock.UpdatedAt.After(merged.UpdatedAt) {
|
||||
merged.UpdatedAt = clock.UpdatedAt
|
||||
}
|
||||
for node, value := range clock.Clock {
|
||||
if existing, ok := merged.Clock[node]; !ok || value > existing {
|
||||
merged.Clock[node] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
return merged
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user