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:
beads/crew/jane
2026-01-20 21:15:00 -08:00
committed by Steve Yegge
parent ea51c4b0bd
commit d3d2326a8b
6 changed files with 490 additions and 29 deletions

View File

@@ -171,6 +171,27 @@ type FederatedStorage interface {
// SyncStatus returns the sync status with a peer.
SyncStatus(ctx context.Context, peer string) (*SyncStatus, error)
// Credential management for SQL user authentication
// AddFederationPeer adds or updates a federation peer with credentials.
AddFederationPeer(ctx context.Context, peer *FederationPeer) error
// GetFederationPeer retrieves a federation peer by name.
// Returns nil if peer doesn't exist.
GetFederationPeer(ctx context.Context, name string) (*FederationPeer, error)
// ListFederationPeers returns all configured federation peers.
ListFederationPeers(ctx context.Context) ([]*FederationPeer, error)
// RemoveFederationPeer removes a federation peer and its credentials.
RemoveFederationPeer(ctx context.Context, name string) error
// PushWithCredentials pushes to a remote using stored credentials.
PushWithCredentials(ctx context.Context, remoteName string) error
// PullWithCredentials pulls from a remote using stored credentials.
PullWithCredentials(ctx context.Context, remoteName string) ([]Conflict, error)
}
// RemoteInfo describes a configured remote.
@@ -188,6 +209,19 @@ type SyncStatus struct {
HasConflicts bool // Whether there are unresolved conflicts
}
// FederationPeer represents a remote peer with authentication credentials.
// Used for peer-to-peer Dolt remotes between Gas Towns with SQL user auth.
type FederationPeer struct {
Name string // Unique name for this peer (used as remote name)
RemoteURL string // Dolt remote URL (e.g., http://host:port/org/db)
Username string // SQL username for authentication
Password string // Password (decrypted, not stored directly)
Sovereignty string // Sovereignty tier: T1, T2, T3, T4
LastSync *time.Time // Last successful sync time
CreatedAt time.Time
UpdatedAt time.Time
}
// IsFederated checks if a storage instance supports federation.
func IsFederated(s Storage) bool {
_, ok := s.(FederatedStorage)