feat(sources): site center backend (credentials, refresh login, user data, health check, delete)

PUT /sites/{id}/credentials by kind (moved from auth-settings, legacy body
accepted), POST refresh-login (async task or wait), POST health-check,
GET user-data history, DELETE /sites/{id} (soft delete, releases kept),
DELETE /site-accounts/{id}, GET /sites?include=accounts; refreshSiteAccount
task with login-failure decisions and auto re-login on auth_expired;
scheduled jobs sites.user_data (6h) and sites.health_check (1h);
settings.sites defaults for rate limit, snapshot interval, UA and proxy.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-28 15:18:40 +08:00
1 parent d6fca25679
commit 05a7706dde
15 files changed
+1602 -179

No files matched your search

+4 -2
View File
@@ -11,6 +11,7 @@ import { EventBus } from "../../src/http/sse.ts";
import { createSourcesIdentityModule } from "../../src/modules/sources-identity/index.ts";
import type { RuntimeOverrides } from "../../src/modules/sources-identity/runtime.ts";
import type { SecretStore, ServerContext, SettingsReader } from "../../src/modules/types.ts";
import { withSchemaLock } from "../auth-settings/harness.ts";
import { DEV_KEY, memoryLogger, memoryStore } from "../helpers.ts";
export const READ_KEY = "w2b-read-key";
@@ -141,7 +142,8 @@ export async function createHarness(name: string, opts: HarnessOptions = {}): Pr
pool: new pg.Pool({ connectionString: PG_URL, max: 8, options: `-c search_path=${schema},public` }),
}),
}) as unknown as Kysely<DB>;
await migrateToLatest(db, { migrationTableSchema: schema });
// 与其他测试进程共用 PG:迁移内省会看到别处正在删除的 schema,用同一把咨询锁排队并重试
await withSchemaLock(() => migrateToLatest(db, { migrationTableSchema: schema }));
const { logger } = memoryLogger();
const engine = fakeEngine();
@@ -206,7 +208,7 @@ export async function createHarness(name: string, opts: HarnessOptions = {}): Pr
},
async close() {
await db.destroy();
await sql.raw(`drop schema if exists ${schema} cascade`).execute(admin);
await withSchemaLock(() => sql.raw(`drop schema if exists ${schema} cascade`).execute(admin));
await admin.destroy();
},
};