feat(federation): add SQL user authentication for peer sync
Merge SQL user authentication with Emma federation sync implementation: - Add federation_peers table for encrypted credential storage - Add credentials.go with AES-256-GCM encryption, SHA-256 key derivation - Extend FederatedStorage interface with credential methods - Add --user, --password, --sovereignty flags to bd federation add-peer - Integrate credentials into PushTo/PullFrom/Fetch via withPeerCredentials - DOLT_REMOTE_USER/PASSWORD env vars protected by mutex for concurrency Credentials automatically used when syncing with peers that have stored auth. Continues: bd-wkumz.10, Closes: bd-4p67y Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
committed by
Steve Yegge
parent
ea51c4b0bd
commit
d3d2326a8b
@@ -12,39 +12,51 @@ import (
|
||||
// These methods enable peer-to-peer synchronization between Gas Towns.
|
||||
|
||||
// PushTo pushes commits to a specific peer remote.
|
||||
// If credentials are stored for this peer, they are used automatically.
|
||||
func (s *DoltStore) PushTo(ctx context.Context, peer string) error {
|
||||
// DOLT_PUSH(remote, branch)
|
||||
_, err := s.db.ExecContext(ctx, "CALL DOLT_PUSH(?, ?)", peer, s.branch)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to push to peer %s: %w", peer, err)
|
||||
}
|
||||
return nil
|
||||
return s.withPeerCredentials(ctx, peer, func() error {
|
||||
// DOLT_PUSH(remote, branch)
|
||||
_, err := s.db.ExecContext(ctx, "CALL DOLT_PUSH(?, ?)", peer, s.branch)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to push to peer %s: %w", peer, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// PullFrom pulls changes from a specific peer remote.
|
||||
// If credentials are stored for this peer, they are used automatically.
|
||||
// Returns any merge conflicts if present.
|
||||
func (s *DoltStore) PullFrom(ctx context.Context, peer string) ([]storage.Conflict, error) {
|
||||
// DOLT_PULL(remote) - pulls and merges
|
||||
_, err := s.db.ExecContext(ctx, "CALL DOLT_PULL(?)", peer)
|
||||
if err != nil {
|
||||
// Check if the error is due to merge conflicts
|
||||
conflicts, conflictErr := s.GetConflicts(ctx)
|
||||
if conflictErr == nil && len(conflicts) > 0 {
|
||||
return conflicts, nil
|
||||
var conflicts []storage.Conflict
|
||||
err := s.withPeerCredentials(ctx, peer, func() error {
|
||||
// DOLT_PULL(remote) - pulls and merges
|
||||
_, pullErr := s.db.ExecContext(ctx, "CALL DOLT_PULL(?)", peer)
|
||||
if pullErr != nil {
|
||||
// Check if the error is due to merge conflicts
|
||||
c, conflictErr := s.GetConflicts(ctx)
|
||||
if conflictErr == nil && len(c) > 0 {
|
||||
conflicts = c
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("failed to pull from peer %s: %w", peer, pullErr)
|
||||
}
|
||||
return nil, fmt.Errorf("failed to pull from peer %s: %w", peer, err)
|
||||
}
|
||||
return nil, nil
|
||||
return nil
|
||||
})
|
||||
return conflicts, err
|
||||
}
|
||||
|
||||
// Fetch fetches refs from a peer without merging.
|
||||
// If credentials are stored for this peer, they are used automatically.
|
||||
func (s *DoltStore) Fetch(ctx context.Context, peer string) error {
|
||||
// DOLT_FETCH(remote)
|
||||
_, err := s.db.ExecContext(ctx, "CALL DOLT_FETCH(?)", peer)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch from peer %s: %w", peer, err)
|
||||
}
|
||||
return nil
|
||||
return s.withPeerCredentials(ctx, peer, func() error {
|
||||
// DOLT_FETCH(remote)
|
||||
_, err := s.db.ExecContext(ctx, "CALL DOLT_FETCH(?)", peer)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch from peer %s: %w", peer, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// ListRemotes returns configured remote names and URLs.
|
||||
|
||||
Reference in New Issue
Block a user