Files
database/zapdb/replicate_pqkey_test.go
zeekayandHanzo Dev fb16ece6a3 feat(zapdb): native ZAP replication — CDC, physical snapshots, PQ, streaming
Replicates a zapdb to S3 via hanzoai/vfs with no keyspace scan in steady state
and post-quantum encryption out of the box.

- CDC incrementals via db.Subscribe (the WAL tail), not Backup(since)'s O(total)
  scan — a 100-key delta out of 200k keys: 2.76us/19KB vs 20ms/1GB (~7000x).
- Physical SST-copy snapshots (sparse, hole-aware): 134ms/25MB vs logical
  158ms/1.25GB/2.2M allocs. Hydrated before Badger opens; incrementals replay on top.
- Streaming codec: Backup -> zstd -> age into a pooled buffer (peak mem = compressed).
- Post-quantum (ML-KEM-768 + X25519 via luxfi/age v1.5.0), client-side before S3.
  Out of the box via REPLICATE_AGE_KEY_FILE (generate+persist, recipient derived).
- Per-DB streams (REPLICATE_AUTO_ON_OPEN) for subprocess VM plugins; backer/restorer
  split (REPLICATE_BACKUP / REPLICATE_SOURCE_ORDINAL) for multi-node.
- Public imports only (hanzoai/vfs v0.4.1, no replace). Verified live on an EVM
  C-chain end-to-end incl. disaster-recovery exact-match. Canonical KV schema
  (zapdb/zapdb.zap) + zero-copy codec (zapkv.go). Renames engine alias badger->zdb.

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-16 02:00:03 +00:00

33 lines
835 B
Go

package zapdb
import (
"path/filepath"
"strings"
"testing"
"github.com/luxfi/age"
)
// TestPQKeyOutOfBox: a key file is generated on first use (ML-KEM-768 hybrid),
// stable across reload, and its derived recipient round-trips a full encrypted
// backup → restore. This is the "PQ native out of the box" path.
func TestPQKeyOutOfBox(t *testing.T) {
kf := filepath.Join(t.TempDir(), "pq.key")
s1, err := loadOrCreatePQKey(kf)
if err != nil {
t.Fatal(err)
}
if !strings.HasPrefix(s1, "AGE-SECRET-KEY-PQ-1") {
t.Fatalf("not a PQ identity: %.24s", s1)
}
if s2, _ := loadOrCreatePQKey(kf); s1 != s2 {
t.Fatal("key not stable across reload")
}
ids, _ := age.ParseIdentities(strings.NewReader(s1))
r := recipientFor(ids[0])
if r == nil {
t.Fatal("no recipient derived from identity")
}
roundTrip(t, r, ids[0])
}