feat(db): allow migration_repair snapshot and event kinds

00028 check constraints would reject a real PG apply. Add goose 00032
with Up/Down so repair snapshots can persist.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weichen
2026-09-14 02:21:44 +00:00
co-authored by Cursor
parent c159786a70
commit e7b46e92d2
2 changed files with 91 additions and 0 deletions
@@ -0,0 +1,58 @@
-- +goose Up
-- Allow explicit migration_repair snapshots/events for legacy canonicalization repair.
-- 00028 rejected this source/change kind, so a real PG apply would fail closed.
ALTER TABLE document_snapshots
DROP CONSTRAINT IF EXISTS chk_snapshot_source_kind;
ALTER TABLE document_snapshots
ADD CONSTRAINT chk_snapshot_source_kind
CHECK (source_kind IN (
'template',
'human',
'agent',
'agent_squad',
'migration',
'system',
'migration_repair'
));
ALTER TABLE document_change_events
DROP CONSTRAINT IF EXISTS chk_change_kind;
ALTER TABLE document_change_events
ADD CONSTRAINT chk_change_kind
CHECK (change_kind IN (
'human_revision',
'agent_commit',
'agent_noop',
'import',
'restore_as_new',
'migration_repair'
));
-- +goose Down
-- Restore 00028 constraints. Fails if any migration_repair rows remain.
ALTER TABLE document_snapshots
DROP CONSTRAINT IF EXISTS chk_snapshot_source_kind;
ALTER TABLE document_snapshots
ADD CONSTRAINT chk_snapshot_source_kind
CHECK (source_kind IN (
'template',
'human',
'agent',
'agent_squad',
'migration',
'system'
));
ALTER TABLE document_change_events
DROP CONSTRAINT IF EXISTS chk_change_kind;
ALTER TABLE document_change_events
ADD CONSTRAINT chk_change_kind
CHECK (change_kind IN (
'human_revision',
'agent_commit',
'agent_noop',
'import',
'restore_as_new'
));
+33
View File
@@ -3,6 +3,8 @@ package db
import (
"context"
"os"
"path/filepath"
"strings"
"testing"
"time"
@@ -45,3 +47,34 @@ func TestMigrationGate_ExpectedFilesMatchAppliedVersion(t *testing.T) {
t.Fatalf("applied schema version %d behind migration files %d", version, expected)
}
}
func TestMigration032_AllowsMigrationRepairKinds(t *testing.T) {
files, err := ListMigrationFiles(ResolveMigrationsDir())
if err != nil {
t.Fatal(err)
}
var found string
for _, name := range files {
if strings.HasPrefix(name, "00032_") && strings.HasSuffix(name, ".sql") {
found = name
break
}
}
if found == "" {
t.Fatal("expected goose 00032 for migration_repair check constraints")
}
raw, err := os.ReadFile(filepath.Join(ResolveMigrationsDir(), found))
if err != nil {
t.Fatal(err)
}
text := string(raw)
if !strings.Contains(text, "-- +goose Up") || !strings.Contains(text, "-- +goose Down") {
t.Fatal("00032 must have Up and Down")
}
if !strings.Contains(text, "chk_snapshot_source_kind") || !strings.Contains(text, "chk_change_kind") {
t.Fatal("00032 must replace source/change kind checks")
}
if strings.Count(text, "'migration_repair'") < 2 {
t.Fatalf("00032 must allow migration_repair on both constraints, got %s", found)
}
}