chore(merge): 整合最新 main 与统一认证变更
ci / verify (pull_request) Successful in 12m18s

合并远端生产 CI、依赖与 API 文档改动,保留统一认证和 SSF 能力。由于远端生产基线已占用 0062,将尚未发布的身份迁移整理为 0063 至 0068 的最终增量 Schema,移除仅用于开发期草稿升级的破坏性迁移步骤。

验证:go test ./...。其余生产门禁在合并提交后继续执行。
This commit is contained in:
2026-07-17 19:06:37 +08:00
100 changed files with 9673 additions and 1799 deletions
@@ -10,149 +10,45 @@ import (
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgconn"
"github.com/jackc/pgx/v5/pgxpool"
)
const identityPairingStartReservationUpgradeMigration = "../../migrations/0073_identity_pairing_start_reservation_upgrade.sql"
const identityPairingStartReservationMigration = "../../migrations/0068_identity_pairing_start_reservation.sql"
func TestIdentityPairingStartReservationUpgradeMigrationDefinesCurrentLifecycle(t *testing.T) {
payload, err := os.ReadFile(identityPairingStartReservationUpgradeMigration)
func TestIdentityPairingStartReservationMigrationDefinesCurrentLifecycle(t *testing.T) {
payload, err := os.ReadFile(identityPairingStartReservationMigration)
if err != nil {
t.Fatal(err)
}
content := strings.ToLower(string(payload))
for _, required := range []string{
"add column if not exists state text",
"add column if not exists revision_id uuid",
"add column if not exists updated_at timestamptz",
"alter column state set not null",
"state text not null default 'starting'",
"revision_id uuid unique references gateway_identity_configuration_revisions",
"updated_at timestamptz not null default now()",
"gateway_identity_pairing_start_state_check",
"foreign key (revision_id)",
"idx_gateway_identity_pairing_start_revision_unique",
"idx_gateway_identity_pairing_start_expiry",
"canonical_pairing",
"on conflict (singleton) do update",
"on conflict do nothing",
} {
if !strings.Contains(content, required) {
t.Fatalf("identity pairing start reservation upgrade migration is missing %q", required)
t.Fatalf("identity pairing start reservation migration is missing %q", required)
}
}
for _, forbidden := range []string{"exchange_token text", "client_secret", "machine_secret", "secret_value"} {
for _, forbidden := range []string{"exchange_token text", "client_secret", "machine_secret", "secret_value", "drop ", "do $"} {
if strings.Contains(content, forbidden) {
t.Fatalf("identity pairing start reservation upgrade migration stores forbidden value field %q", forbidden)
t.Fatalf("identity pairing start reservation migration contains forbidden content %q", forbidden)
}
}
}
func TestIdentityPairingStartReservationUpgradeMigratesLegacyShapeAndIsIdempotent(t *testing.T) {
func TestIdentityPairingStartReservationMigrationSeedsOutstandingPairing(t *testing.T) {
pool := newIdentityMigrationPostgresTestSchema(t)
ctx := context.Background()
applyIdentityPairingStartReservationPrerequisites(t, ctx, pool)
revisionID, pairingID, pairingExpiresAt := seedOutstandingIdentityPairingForReservationMigration(t, ctx, pool)
legacyAttemptID := uuid.NewString()
if _, err := pool.Exec(ctx, `
CREATE TABLE gateway_identity_pairing_start_reservation (
singleton boolean PRIMARY KEY DEFAULT true CHECK (singleton),
attempt_id uuid NOT NULL UNIQUE,
expires_at timestamptz NOT NULL,
created_at timestamptz NOT NULL DEFAULT now()
)`); err != nil {
t.Fatalf("create legacy pairing start reservation: %v", err)
}
if _, err := pool.Exec(ctx, `
INSERT INTO gateway_identity_pairing_start_reservation(singleton,attempt_id,expires_at)
VALUES(true,$1::uuid,now()+interval '2 minutes')`, legacyAttemptID); err != nil {
t.Fatalf("seed legacy pairing start reservation: %v", err)
}
applyIdentityMigrationTestFile(t, ctx, pool, identityPairingStartReservationUpgradeMigration)
assertCurrentIdentityPairingStartReservation(t, ctx, pool, pairingID, revisionID, pairingExpiresAt)
assertIdentityPairingStartReservationSchema(t, ctx, pool)
// Migration runners apply each version once, but a repeat execution proves
// that recovery from an interrupted/manual rollout does not duplicate state.
applyIdentityMigrationTestFile(t, ctx, pool, identityPairingStartReservationUpgradeMigration)
assertCurrentIdentityPairingStartReservation(t, ctx, pool, pairingID, revisionID, pairingExpiresAt)
assertIdentityPairingStartReservationSchema(t, ctx, pool)
}
func TestIdentityPairingStartReservationUpgradePreservesLegacyStartingLease(t *testing.T) {
pool := newIdentityMigrationPostgresTestSchema(t)
ctx := context.Background()
applyIdentityPairingStartReservationPrerequisites(t, ctx, pool)
attemptID := uuid.NewString()
expiresAt := time.Now().UTC().Add(2 * time.Minute).Truncate(time.Microsecond)
if _, err := pool.Exec(ctx, `
CREATE TABLE gateway_identity_pairing_start_reservation (
singleton boolean PRIMARY KEY DEFAULT true CHECK (singleton),
attempt_id uuid NOT NULL UNIQUE,
expires_at timestamptz NOT NULL,
created_at timestamptz NOT NULL DEFAULT now()
)`); err != nil {
t.Fatalf("create legacy pairing start reservation: %v", err)
}
if _, err := pool.Exec(ctx, `
INSERT INTO gateway_identity_pairing_start_reservation(singleton,attempt_id,expires_at)
VALUES(true,$1::uuid,$2)`, attemptID, expiresAt); err != nil {
t.Fatalf("seed legacy starting reservation: %v", err)
}
applyIdentityMigrationTestFile(t, ctx, pool, identityPairingStartReservationUpgradeMigration)
applyIdentityMigrationTestFile(t, ctx, pool, identityPairingStartReservationUpgradeMigration)
var gotAttemptID, state string
var revisionID *string
var gotExpiresAt, updatedAt time.Time
if err := pool.QueryRow(ctx, `
SELECT attempt_id::text,state,revision_id::text,expires_at,updated_at
FROM gateway_identity_pairing_start_reservation`).
Scan(&gotAttemptID, &state, &revisionID, &gotExpiresAt, &updatedAt); err != nil {
t.Fatalf("read upgraded legacy starting reservation: %v", err)
}
if gotAttemptID != attemptID || state != "starting" || revisionID != nil ||
!gotExpiresAt.Equal(expiresAt) || updatedAt.IsZero() {
t.Fatalf("unexpected upgraded starting reservation attempt=%q state=%q revision=%v expires=%v updated=%v",
gotAttemptID, state, revisionID, gotExpiresAt, updatedAt)
}
_, err := pool.Exec(ctx, `UPDATE gateway_identity_pairing_start_reservation SET state='paired'`)
requireIdentityPairingStartReservationMigrationCode(t, err, "23514", "paired reservation without revision")
}
func TestIdentityPairingStartReservationUpgradeAcceptsFresh0071Schema(t *testing.T) {
pool := newIdentityMigrationPostgresTestSchema(t)
ctx := context.Background()
applyIdentityPairingStartReservationPrerequisites(t, ctx, pool)
revisionID, pairingID, pairingExpiresAt := seedOutstandingIdentityPairingForReservationMigration(t, ctx, pool)
applyIdentityMigrationTestFile(t, ctx, pool, "../../migrations/0071_identity_pairing_start_reservation.sql")
assertCurrentIdentityPairingStartReservation(t, ctx, pool, pairingID, revisionID, pairingExpiresAt)
applyIdentityMigrationTestFile(t, ctx, pool, identityPairingStartReservationUpgradeMigration)
applyIdentityMigrationTestFile(t, ctx, pool, identityPairingStartReservationUpgradeMigration)
assertCurrentIdentityPairingStartReservation(t, ctx, pool, pairingID, revisionID, pairingExpiresAt)
assertIdentityPairingStartReservationSchema(t, ctx, pool)
}
func applyIdentityPairingStartReservationPrerequisites(t *testing.T, ctx context.Context, pool *pgxpool.Pool) {
t.Helper()
for _, migration := range []string{
"../../migrations/0067_identity_configuration_revisions.sql",
"../../migrations/0068_identity_onboarding_exchanges.sql",
"../../migrations/0069_identity_pairing_cancellation.sql",
"../../migrations/0065_identity_configuration_revisions.sql",
"../../migrations/0066_identity_onboarding_exchanges.sql",
} {
applyIdentityMigrationTestFile(t, ctx, pool, migration)
}
}
func seedOutstandingIdentityPairingForReservationMigration(
t *testing.T,
ctx context.Context,
pool *pgxpool.Pool,
) (string, string, time.Time) {
t.Helper()
revisionID := uuid.NewString()
pairingID := uuid.NewString()
expiresAt := time.Now().UTC().Add(30 * time.Minute).Truncate(time.Microsecond)
@@ -170,79 +66,31 @@ INSERT INTO gateway_identity_onboarding_exchanges (
pairingID, revisionID, uuid.NewString(), "identity-exchange-"+pairingID, expiresAt); err != nil {
t.Fatalf("seed identity exchange for pairing reservation migration: %v", err)
}
return revisionID, pairingID, expiresAt
}
func assertCurrentIdentityPairingStartReservation(
t *testing.T,
ctx context.Context,
pool *pgxpool.Pool,
wantAttemptID string,
wantRevisionID string,
wantExpiresAt time.Time,
) {
t.Helper()
var count int
var attemptID, state, revisionID string
var expiresAt, updatedAt time.Time
applyIdentityMigrationTestFile(t, ctx, pool, identityPairingStartReservationMigration)
var attemptID, state, reservedRevisionID string
var gotExpiresAt, updatedAt time.Time
if err := pool.QueryRow(ctx, `
SELECT count(*) OVER (),attempt_id::text,state,revision_id::text,expires_at,updated_at
FROM gateway_identity_pairing_start_reservation`).
Scan(&count, &attemptID, &state, &revisionID, &expiresAt, &updatedAt); err != nil {
t.Fatalf("read upgraded pairing start reservation: %v", err)
SELECT attempt_id::text,state,revision_id::text,expires_at,updated_at
FROM gateway_identity_pairing_start_reservation`).Scan(
&attemptID, &state, &reservedRevisionID, &gotExpiresAt, &updatedAt,
); err != nil {
t.Fatalf("read pairing start reservation: %v", err)
}
if count != 1 || attemptID != wantAttemptID || state != "paired" || revisionID != wantRevisionID ||
!expiresAt.Equal(wantExpiresAt) || updatedAt.IsZero() {
t.Fatalf("unexpected upgraded pairing reservation count=%d attempt=%q state=%q revision=%q expires=%v updated=%v",
count, attemptID, state, revisionID, expiresAt, updatedAt)
}
}
func assertIdentityPairingStartReservationSchema(t *testing.T, ctx context.Context, pool *pgxpool.Pool) {
t.Helper()
for _, column := range []struct {
name string
wantDefaultFragment string
}{
{name: "state", wantDefaultFragment: "starting"},
{name: "updated_at", wantDefaultFragment: "now()"},
} {
var nullable, defaultExpression string
if err := pool.QueryRow(ctx, `
SELECT is_nullable,COALESCE(column_default,'')
FROM information_schema.columns
WHERE table_schema=current_schema()
AND table_name='gateway_identity_pairing_start_reservation'
AND column_name=$1`, column.name).Scan(&nullable, &defaultExpression); err != nil {
t.Fatalf("read upgraded pairing reservation column %s: %v", column.name, err)
}
if nullable != "NO" || !strings.Contains(defaultExpression, column.wantDefaultFragment) {
t.Fatalf("pairing reservation column %s nullable=%q default=%q", column.name, nullable, defaultExpression)
}
}
var expiryIndex, revisionIndex string
if err := pool.QueryRow(ctx, `SELECT pg_get_indexdef('idx_gateway_identity_pairing_start_expiry'::regclass)`).
Scan(&expiryIndex); err != nil {
t.Fatalf("read pairing reservation expiry index: %v", err)
}
if err := pool.QueryRow(ctx, `SELECT pg_get_indexdef('idx_gateway_identity_pairing_start_revision_unique'::regclass)`).
Scan(&revisionIndex); err != nil {
t.Fatalf("read pairing reservation revision index: %v", err)
}
if !strings.Contains(strings.ToLower(expiryIndex), "(state, expires_at)") ||
!strings.Contains(strings.ToLower(revisionIndex), "unique") ||
!strings.Contains(strings.ToLower(revisionIndex), "(revision_id)") {
t.Fatalf("unexpected pairing reservation indexes expiry=%q revision=%q", expiryIndex, revisionIndex)
if attemptID != pairingID || state != "paired" || reservedRevisionID != revisionID ||
!gotExpiresAt.Equal(expiresAt) || updatedAt.IsZero() {
t.Fatalf("unexpected pairing reservation attempt=%q state=%q revision=%q expires=%v updated=%v",
attemptID, state, reservedRevisionID, gotExpiresAt, updatedAt)
}
_, err := pool.Exec(ctx, `UPDATE gateway_identity_pairing_start_reservation SET state='starting'`)
requireIdentityPairingStartReservationMigrationCode(t, err, "23514", "starting reservation with revision")
requirePairingReservationMigrationCode(t, err, "23514", "starting reservation with revision")
_, err = pool.Exec(ctx, `UPDATE gateway_identity_pairing_start_reservation SET revision_id=$1::uuid`, uuid.NewString())
requireIdentityPairingStartReservationMigrationCode(t, err, "23503", "reservation with unknown revision")
requirePairingReservationMigrationCode(t, err, "23503", "reservation with unknown revision")
}
func requireIdentityPairingStartReservationMigrationCode(t *testing.T, err error, wantCode, operation string) {
func requirePairingReservationMigrationCode(t *testing.T, err error, wantCode, operation string) {
t.Helper()
if err == nil {
t.Fatalf("%s unexpectedly satisfied migration constraints", operation)
+12
View File
@@ -24,6 +24,10 @@ func main() {
os.Exit(1)
}
defer conn.Close(ctx)
if _, err := conn.Exec(ctx, "SET standard_conforming_strings = on"); err != nil {
logger.Error("enforce standard SQL string semantics failed", "error", err)
os.Exit(1)
}
if _, err := conn.Exec(ctx, `
CREATE TABLE IF NOT EXISTS schema_migrations (
@@ -64,6 +68,14 @@ CREATE TABLE IF NOT EXISTS schema_migrations (
logger.Error("begin migration failed", "version", version, "error", err)
os.Exit(1)
}
// Pin string parsing semantics inside every migration transaction. A
// previous migration may have changed the session GUC, while each file is
// parsed and executed independently.
if _, err := tx.Exec(ctx, "SET LOCAL standard_conforming_strings = on"); err != nil {
_ = tx.Rollback(ctx)
logger.Error("enforce migration SQL string semantics failed", "version", version, "error", err)
os.Exit(1)
}
if _, err := tx.Exec(ctx, string(sqlBytes)); err != nil {
_ = tx.Rollback(ctx)
logger.Error("execute migration failed", "version", version, "error", err)
+43 -51
View File
@@ -14,42 +14,41 @@ import (
"github.com/jackc/pgx/v5/pgxpool"
)
func TestSecurityEventIdempotencyRepairMigrationExists(t *testing.T) {
payload, err := os.ReadFile("../../migrations/0064_security_event_connection_idempotency_repair.sql")
func TestSecurityEventSchemaMigrationsDefineCurrentLifecycle(t *testing.T) {
streamPayload, err := os.ReadFile("../../migrations/0063_oidc_security_events.sql")
if err != nil {
t.Fatalf("read repair migration: %v", err)
t.Fatalf("read security event stream migration: %v", err)
}
sql := string(payload)
streamSQL := string(streamPayload)
for _, statement := range []string{
"CREATE TABLE IF NOT EXISTS gateway_security_event_connection_idempotency",
"CREATE INDEX IF NOT EXISTS idx_gateway_security_event_connection_idempotency_created",
} {
if !strings.Contains(sql, statement) {
t.Fatalf("repair migration is missing %q", statement)
}
}
}
func TestSecurityEventVerificationStateRepairMigrationExists(t *testing.T) {
payload, err := os.ReadFile("../../migrations/0065_security_event_verification_state_repair.sql")
if err != nil {
t.Fatalf("read verification state repair migration: %v", err)
}
sql := string(payload)
for _, statement := range []string{
"ADD COLUMN IF NOT EXISTS stream_status",
"ADD COLUMN IF NOT EXISTS created_at",
"CREATE TABLE IF NOT EXISTS gateway_security_event_stream_state",
"CREATE TABLE IF NOT EXISTS gateway_security_event_verification_challenges",
"CREATE INDEX IF NOT EXISTS idx_gateway_security_event_challenges_expiry",
} {
if !strings.Contains(sql, statement) {
t.Fatalf("verification state repair migration is missing %q", statement)
if !strings.Contains(streamSQL, statement) {
t.Fatalf("security event stream migration is missing %q", statement)
}
}
connectionPayload, err := os.ReadFile("../../migrations/0064_security_event_connections.sql")
if err != nil {
t.Fatalf("read security event connection migration: %v", err)
}
connectionSQL := string(connectionPayload)
for _, statement := range []string{
"CREATE TABLE IF NOT EXISTS gateway_security_event_connections",
"management_client_id text",
"management_credential_ref text",
"CREATE TABLE IF NOT EXISTS gateway_security_event_connection_idempotency",
} {
if !strings.Contains(connectionSQL, statement) {
t.Fatalf("security event connection migration is missing %q", statement)
}
}
}
func TestIdentityConfigurationRevisionMigrationDefinesSecretReferencesAndSingleActiveRevision(t *testing.T) {
payload, err := os.ReadFile("../../migrations/0067_identity_configuration_revisions.sql")
payload, err := os.ReadFile("../../migrations/0065_identity_configuration_revisions.sql")
if err != nil {
t.Fatal(err)
}
@@ -58,6 +57,7 @@ func TestIdentityConfigurationRevisionMigrationDefinesSecretReferencesAndSingleA
"CREATE TABLE IF NOT EXISTS gateway_identity_configuration_revisions",
"machine_credential_ref text",
"session_encryption_key_ref text",
"security_event_configuration_url text",
"WHERE state = 'active'",
"CHECK (state IN ('draft','validated','active','superseded','failed'))",
} {
@@ -73,7 +73,7 @@ func TestIdentityConfigurationRevisionMigrationDefinesSecretReferencesAndSingleA
}
func TestIdentityOnboardingExchangeMigrationStoresOnlySecretReferences(t *testing.T) {
payload, err := os.ReadFile("../../migrations/0068_identity_onboarding_exchanges.sql")
payload, err := os.ReadFile("../../migrations/0066_identity_onboarding_exchanges.sql")
if err != nil {
t.Fatal(err)
}
@@ -81,7 +81,8 @@ func TestIdentityOnboardingExchangeMigrationStoresOnlySecretReferences(t *testin
for _, required := range []string{
"create table if not exists gateway_identity_onboarding_exchanges",
"exchange_token_ref text not null",
"security_event_configuration_url text",
"cleanup_status text not null default 'none'",
"security_event_credential_handoff_unsafe",
} {
if !strings.Contains(content, required) {
t.Fatalf("identity onboarding migration is missing %q", required)
@@ -94,8 +95,8 @@ func TestIdentityOnboardingExchangeMigrationStoresOnlySecretReferences(t *testin
}
}
func TestIdentityPairingCancellationMigrationSeparatesCleanupLifecycle(t *testing.T) {
payload, err := os.ReadFile("../../migrations/0069_identity_pairing_cancellation.sql")
func TestIdentityOnboardingMigrationDefinesCancellationLifecycle(t *testing.T) {
payload, err := os.ReadFile("../../migrations/0066_identity_onboarding_exchanges.sql")
if err != nil {
t.Fatal(err)
}
@@ -106,9 +107,6 @@ func TestIdentityPairingCancellationMigrationSeparatesCleanupLifecycle(t *testin
"cleanup_completed_at",
"idx_gateway_identity_onboarding_cleanup",
"last_error_category",
"set last_error_category = 'pairing_step_failed'",
"set local lock_timeout = '10s'",
"set local statement_timeout = '60s'",
} {
if !strings.Contains(content, required) {
t.Fatalf("identity pairing cancellation migration is missing %q", required)
@@ -121,14 +119,14 @@ func TestIdentityPairingCancellationMigrationSeparatesCleanupLifecycle(t *testin
}
}
func TestIdentityPairingErrorCategoryUpgradeMigrationExists(t *testing.T) {
payload, err := os.ReadFile("../../migrations/0074_identity_pairing_error_categories.sql")
func TestIdentityOnboardingMigrationDefinesFinalErrorCategories(t *testing.T) {
payload, err := os.ReadFile("../../migrations/0066_identity_onboarding_exchanges.sql")
if err != nil {
t.Fatal(err)
}
content := strings.ToLower(string(payload))
for _, required := range []string{
"drop constraint if exists gateway_identity_onboarding_error_category_check",
"gateway_identity_onboarding_error_category_check",
"security_event_credential_handoff_unsafe",
"security_event_connection_binding_missing",
"security_event_connection_binding_unavailable",
@@ -142,18 +140,14 @@ func TestIdentityPairingErrorCategoryUpgradeMigrationExists(t *testing.T) {
}
}
func TestIdentityPairingErrorCategoryUpgradeMigrationExecutesAgainstCurrentSchema(t *testing.T) {
func TestIdentityPairingErrorCategoriesExecuteAgainstCurrentSchema(t *testing.T) {
pool := newIdentityMigrationPostgresTestSchema(t)
ctx := context.Background()
for _, migration := range []string{
"../../migrations/0067_identity_configuration_revisions.sql",
"../../migrations/0068_identity_onboarding_exchanges.sql",
"../../migrations/0069_identity_pairing_cancellation.sql",
"../../migrations/0070_identity_secret_cleanup_queue.sql",
"../../migrations/0071_identity_pairing_start_reservation.sql",
"../../migrations/0072_identity_secret_cleanup_claim_lifecycle.sql",
"../../migrations/0073_identity_pairing_start_reservation_upgrade.sql",
"../../migrations/0074_identity_pairing_error_categories.sql",
"../../migrations/0065_identity_configuration_revisions.sql",
"../../migrations/0066_identity_onboarding_exchanges.sql",
"../../migrations/0067_identity_secret_cleanup_queue.sql",
"../../migrations/0068_identity_pairing_start_reservation.sql",
} {
applyIdentityMigrationTestFile(t, ctx, pool, migration)
}
@@ -193,7 +187,7 @@ SET last_error_category='credential_secret_leaked' WHERE id=$1::uuid`, pairingID
}
func TestIdentitySecretCleanupQueueMigrationStoresOnlyReferences(t *testing.T) {
payload, err := os.ReadFile("../../migrations/0070_identity_secret_cleanup_queue.sql")
payload, err := os.ReadFile("../../migrations/0067_identity_secret_cleanup_queue.sql")
if err != nil {
t.Fatal(err)
}
@@ -219,11 +213,11 @@ func TestIdentitySecretCleanupQueueMigrationStoresOnlyReferences(t *testing.T) {
}
}
func TestIdentityPairingCancellationMigrationExecutesAgainstLegacyData(t *testing.T) {
func TestIdentityPairingCancellationLifecycleRejectsPartialStates(t *testing.T) {
pool := newIdentityMigrationPostgresTestSchema(t)
ctx := context.Background()
applyIdentityMigrationTestFile(t, ctx, pool, "../../migrations/0067_identity_configuration_revisions.sql")
applyIdentityMigrationTestFile(t, ctx, pool, "../../migrations/0068_identity_onboarding_exchanges.sql")
applyIdentityMigrationTestFile(t, ctx, pool, "../../migrations/0065_identity_configuration_revisions.sql")
applyIdentityMigrationTestFile(t, ctx, pool, "../../migrations/0066_identity_onboarding_exchanges.sql")
revisionID, pairingID := uuid.NewString(), uuid.NewString()
if _, err := pool.Exec(ctx, `
@@ -236,13 +230,11 @@ INSERT INTO gateway_identity_configuration_revisions (
if _, err := pool.Exec(ctx, `
INSERT INTO gateway_identity_onboarding_exchanges (
id,revision_id,remote_exchange_id,exchange_token_ref,status,remote_version,expires_at,last_error_category
) VALUES ($1::uuid,$2::uuid,$3::uuid,$4,'credentials_saved',4,now() + interval '30 minutes','secret_token_abcdef')`,
) VALUES ($1::uuid,$2::uuid,$3::uuid,$4,'credentials_saved',4,now() + interval '30 minutes','pairing_step_failed')`,
pairingID, revisionID, uuid.NewString(), "identity-exchange-"+pairingID); err != nil {
t.Fatalf("seed legacy onboarding exchange: %v", err)
}
applyIdentityMigrationTestFile(t, ctx, pool, "../../migrations/0069_identity_pairing_cancellation.sql")
var status, cleanupStatus, errorCategory string
var cancelledAt, cleanupCompletedAt *time.Time
if err := pool.QueryRow(ctx, `