clavitor/clavis/clavis-vault/edition/replication.go

85 lines
2.6 KiB
Go

//go:build commercial
// Package edition - Commercial replication implementation.
// This file is built ONLY when the "commercial" build tag is specified.
//
// Real-time replication to backup POPs (Calgary/Zurich).
// Community Edition does not have replication functionality.
//
// This is PROPRIETARY code - part of Commercial Edition licensing.
package edition
import (
"context"
"log"
"time"
)
// startReplication begins the background replication goroutine.
// Called at startup in commercial edition via StartReplication variable.
func startReplication(ctx context.Context, dataDir string) {
if globalConfig == nil || globalConfig.ReplicationConfig == nil || globalConfig.ReplicationConfig.PrimaryPOP == "" {
log.Printf("Commercial edition: replication disabled (no backup POP configured)")
return
}
log.Printf("Commercial edition: replication enabled to %s", globalConfig.ReplicationConfig.PrimaryPOP)
go func() {
ticker := time.NewTicker(time.Duration(globalConfig.ReplicationConfig.PollInterval) * time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
if err := replicateBatch(ctx, dataDir); err != nil {
log.Printf("replication error: %v", err)
// Alert operator on repeated failures
// TODO: Track consecutive failures, alert after threshold
}
}
}
}()
}
// replicateBatch sends unreplicated entries to backup POP.
func replicateBatch(ctx context.Context, dataDir string) error {
// Implementation TBD - stub for now
// 1. Open DB
// 2. Call lib.EntryListUnreplicated()
// 3. Encrypt/encode entries
// 4. POST to backup POP
// 5. Mark replicated with lib.EntryMarkReplicated()
return nil
}
// ReplicatedEntry represents an entry being sent to backup POP.
type ReplicatedEntry struct {
EntryID string `json:"entry_id"`
Type string `json:"type"`
Title string `json:"title"`
TitleIdx string `json:"title_idx"`
Data []byte `json:"data"` // Encrypted blob
DataLevel int `json:"data_level"`
Scopes string `json:"scopes"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
Version int `json:"version"`
}
// ReplicationRequest is sent to backup POP.
type ReplicationRequest struct {
SourcePOP string `json:"source_pop"`
Entries []ReplicatedEntry `json:"entries"`
Timestamp int64 `json:"timestamp"`
}
// ReplicationResponse from backup POP.
type ReplicationResponse struct {
Accepted []string `json:"accepted"` // EntryIDs successfully stored
Rejected []string `json:"rejected"` // EntryIDs failed validation
Duplicate []string `json:"duplicate"` // EntryIDs already present (version conflict)
}