fix: harden backup restore, first-user race, and several reliability issues

- Block all non-health API requests with 503 while a database restore is in progress (`withDatabaseAccessBlocked` in `@sofa/db/client`); pause and resume cron jobs around the restore window
- Replace the two-hook first-user admin promotion with an atomic `claimInitialAdmin` query that uses a DB-level unique constraint so concurrent sign-ups during the first-run window can't each see `userCount === 0`
- Fix `refreshAvailability` to always call `replaceAvailabilityTransaction` (clearing stale rows) even when TMDB returns no US providers, instead of returning early and leaving old data in place
- Fix `performUpdateCheck` to read `release_url` (snake_case) from the public API response instead of `releaseUrl`
- Fix `createJob` import handler to catch `SQLITE_CONSTRAINT_UNIQUE` and surface it as an `IMPORT_ALREADY_RUNNING` conflict error instead of a 500
- Relax public API telemetry schema to accept `string | number` for `users` and `titles` fields
- Add tests for availability clearing, import deduplication, and `claimInitialAdmin`
This commit is contained in:
2026-03-21 16:16:37 -04:00
parent f676cea237
commit 58cf2e689f
23 changed files with 3513 additions and 86 deletions
+27 -2
View File
@@ -1,8 +1,15 @@
import { beforeEach, describe, expect, test } from "bun:test";
import { clearAllTables, insertUser } from "@sofa/db/test-utils";
import { user } from "@sofa/db/schema";
import { clearAllTables, eq, insertUser, testDb } from "@sofa/db/test-utils";
import { getSetting, getUserCount, isRegistrationOpen, setSetting } from "../src/settings";
import {
claimInitialAdmin,
getSetting,
getUserCount,
isRegistrationOpen,
setSetting,
} from "../src/settings";
beforeEach(() => {
clearAllTables();
@@ -65,3 +72,21 @@ describe("isRegistrationOpen", () => {
expect(isRegistrationOpen()).toBe(false);
});
});
describe("claimInitialAdmin", () => {
test("promotes the earliest user to admin and closes registration", () => {
insertUser("user-1");
insertUser("user-2");
expect(claimInitialAdmin("user-2")).toBe(false);
expect(claimInitialAdmin("user-1")).toBe(true);
expect(claimInitialAdmin("user-1")).toBe(false);
const firstUser = testDb.select().from(user).where(eq(user.id, "user-1")).get();
const secondUser = testDb.select().from(user).where(eq(user.id, "user-2")).get();
expect(firstUser?.role).toBe("admin");
expect(secondUser?.role).toBe("user");
expect(getSetting("registrationOpen")).toBe("false");
});
});