feat: ship loose-offline dbsync (validate, agent push, LWW audit)
Add UUID/FK channel checks, agent whitelist/push APIs, bindings, super-admin LWW audit with rollback, reconcile rate limits, and sync docs. Default customers stay opt-in; company conflict UI is removed. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
65
platform/internal/dbsync/validate_test.go
Normal file
65
platform/internal/dbsync/validate_test.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package dbsync
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIsTextLikePK(t *testing.T) {
|
||||
good := []string{"TEXT", "VARCHAR(36)", "uuid", "CHARACTER VARYING", "NVARCHAR(64)", "char(36)"}
|
||||
for _, g := range good {
|
||||
if !isTextLikePK(g) {
|
||||
t.Fatalf("expected text-like: %s", g)
|
||||
}
|
||||
}
|
||||
bad := []string{"INTEGER", "INT", "BIGINT", "SERIAL", "BIGSERIAL", "int(11)", "NUMERIC", "DECIMAL(10,2)"}
|
||||
for _, b := range bad {
|
||||
if isTextLikePK(b) {
|
||||
t.Fatalf("expected reject: %s", b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateChannelConfigEmpty(t *testing.T) {
|
||||
ch := &Channel{}
|
||||
if err := ValidateChannelConfig(ch); err == nil {
|
||||
t.Fatal("expected error for empty tables")
|
||||
}
|
||||
ch.Local.Tables = []string{"orders"}
|
||||
if err := ValidateChannelConfig(ch); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateChannelAgainstDBRejectsIntegerPK(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
dsn := "file:" + filepath.ToSlash(filepath.Join(dir, "t.db")) + "?_pragma=foreign_keys(1)"
|
||||
db, err := Open(DriverSQLite, dsn)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
if _, err = db.Exec(`CREATE TABLE orders (id INTEGER PRIMARY KEY, title TEXT)`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err = db.Exec(`CREATE TABLE orders_uuid (id TEXT PRIMARY KEY, title TEXT)`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
bad := &Channel{
|
||||
Local: Endpoint{Driver: DriverSQLite, DSN: dsn, Tables: []string{"orders"}},
|
||||
Remote: Endpoint{Driver: DriverSQLite, DSN: dsn, Tables: []string{"orders"}},
|
||||
}
|
||||
if err := ValidateChannelAgainstDB(context.Background(), bad); err == nil {
|
||||
t.Fatal("expected reject INTEGER PK")
|
||||
}
|
||||
|
||||
good := &Channel{
|
||||
Local: Endpoint{Driver: DriverSQLite, DSN: dsn, Tables: []string{"orders_uuid"}},
|
||||
Remote: Endpoint{Driver: DriverSQLite, DSN: dsn, Tables: []string{"orders_uuid"}},
|
||||
}
|
||||
if err := ValidateChannelAgainstDB(context.Background(), good); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user