Files
goclaw/tests/integration/backup_export_registry_test.go
thotam 25eaa0166f fix(backup): repair tenant backup/restore (config_secrets order, hooks registry, restore conn check) (#1357)
Closes #1076, #1338.

Fix A — tenant backup aborted with SQLSTATE 42703 "column id does not
exist" because exportQuery() hardcoded ORDER BY id. Several tenant-scoped
tables have composite PKs and no id column. Add a TableDef.OrderBy field,
honor it in exportQuery(), and set it for every id-less registry table:
config_secrets, agent_team_members, tenant_hook_budget, system_configs,
builtin_tool_tenant_configs, skill_tenant_configs, user_agent_profiles.

Fix B — hooks, tenant_hook_budget and webhook config were missing from
the backup registry, silently dropping their data on backup/restore. Add
hooks, tenant_hook_budget, webhooks (preserve) plus the hook_agents junction
(via ParentJoin through hooks, composite PK), and mark hook_executions and
webhook_calls as ephemeral in the skipped list.

Fix C — restoring on a fresh server failed with "N active DB connection(s)
detected" because the gateway's own pool connections were counted as active
clients. Tag pool connections with application_name='goclaw' (pg.OpenDB) and
exclude them in CheckActiveConnections; genuine external clients still block.

Adds unit + integration regression tests, including an export-over-every-
registered-table test that surfaced the additional id-less tables.
2026-07-05 11:56:36 +07:00

33 lines
1.0 KiB
Go

//go:build integration
package integration
import (
"bytes"
"context"
"testing"
"github.com/nextlevelbuilder/goclaw/internal/backup"
)
// TestBackup_ExportAllRegistryTables_NoSQLError is an end-to-end regression for
// issue #1076/#1338: exporting config_secrets (and other composite-PK tables)
// failed with SQLSTATE 42703 "column id does not exist" because exportQuery
// hardcoded ORDER BY id. PostgreSQL validates the ORDER BY column at plan time,
// so the export fails even for an empty tenant. Running ExportTable over every
// registered table proves each query is valid against the real schema — including
// the hook_agents ParentJoin.
func TestBackup_ExportAllRegistryTables_NoSQLError(t *testing.T) {
db := testDB(t)
tenantID, _ := seedTenantAgent(t, db)
for _, tbl := range backup.TenantTables() {
t.Run(tbl.Name, func(t *testing.T) {
var buf bytes.Buffer
if _, err := backup.ExportTable(context.Background(), db, tbl, tenantID, &buf); err != nil {
t.Errorf("ExportTable(%s): %v", tbl.Name, err)
}
})
}
}