fix(organize,identity,sites,pi): W10-pre backend fixes from v0.2 visual QA
- slot: new manual_verify event (attention -> verifying, with reason); a
successful organize of a download whose slot is in attention goes back
through verifying and lands by verify_passed on the actually imported
assets; the download's organize_blocked decision is resolved with
resolution {key: manual_organize | organize_retry, organizationRecordId} (U1)
- acquisition: plan purpose is upgrade only when the slot already has a
current asset; a movie slot gap is a fill (U7)
- identity: entities created from TMDB details get metadata fields projected
in the same transaction; TMDB aliases deduped by normalized text, site-title
aliases skipped when the text already exists (U9)
- pi: auth-mode test of a custom Base URL no longer marks the upstream ok, and
says to use the minimal completion to probe the endpoint (U2)
- sites: PUT /sites/{id}/credentials replaces same-kind secrets in place and
names new secrets with site id + random suffix (secret.name is unique; was a
500 on update); M-Team user data uses config/definition apiBaseUrl instead
of deriving api.<domain> from the site URL (Invalid URL on IP/local bases)
- copy: setup error says 初始化口令; backup job points at umt backup
- tests: schema expected tables add site_user_data; migration round-trip
timeout 60s; fake secrets honor label as name; vertical/resolve/pi/slot/
site-center tests for the above
- docs: 09-visual-qa W10-pre status table (U3 root cause: outbox events are
never mirrored to SSE)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
b7a7fd3958
commit
2b8fe667a5
20 files changed
+298
-42
No files matched your search
@@ -99,6 +99,8 @@ const EXPECTED_TABLES = [
|
||||
// W7-C 定时任务注册表(0028)
|
||||
"scheduled_job",
|
||||
"scheduled_job_run",
|
||||
// W9-A 站点用户数据(0031)
|
||||
"site_user_data",
|
||||
// W9-C 命名模板版本(0032)
|
||||
"naming_template_version",
|
||||
// W9-D 规则组(0033)
|
||||
@@ -381,5 +383,5 @@ describe.skipIf(skip)("schema migrations (real PG)", () => {
|
||||
const up = await migrator.migrateToLatest();
|
||||
expect(up.error).toBeUndefined();
|
||||
expect(await tables()).toEqual(EXPECTED_TABLES);
|
||||
});
|
||||
}, 60_000);
|
||||
});
|
||||
@@ -25,6 +25,8 @@ export type SlotEvent =
|
||||
| { type: "upgrade_found" }
|
||||
| { type: "upgrade_cancelled" }
|
||||
| { type: "attention_resolved"; hasAsset: boolean }
|
||||
/** 需处理的 Slot 经人工整理拿到了新资产:回到核验,由 verify_passed 以实际入库资产定终态 */
|
||||
| { type: "manual_verify"; reason: string }
|
||||
| { type: "asset_missing_confirmed" };
|
||||
|
||||
export class SlotTransitionError extends Error {
|
||||
@@ -80,6 +82,9 @@ export function transition(state: SlotState, event: SlotEvent): SlotState {
|
||||
case "attention_resolved":
|
||||
if (status === "attention") return { status: event.hasAsset ? "satisfied" : "empty", hasAsset: event.hasAsset };
|
||||
return bad();
|
||||
case "manual_verify":
|
||||
if (status === "attention") return { status: "verifying", hasAsset };
|
||||
return bad();
|
||||
case "asset_missing_confirmed":
|
||||
// 只接受"确认缺失"(对账多次观察后);单次观察失败不得触发(失败 ≠ 不存在)
|
||||
if (status === "satisfied" || status === "upgrade_pending") return { status: "attention", hasAsset: false };
|
||||
|
||||
@@ -205,6 +205,13 @@ describe("Slot 状态机", () => {
|
||||
hasAsset: false,
|
||||
});
|
||||
});
|
||||
it("需处理经人工整理回到核验,再按实际资产落终态(manual_verify)", () => {
|
||||
const st = transition(s("attention"), { type: "manual_verify", reason: "manual_organize" });
|
||||
expect(st).toEqual({ status: "verifying", hasAsset: false });
|
||||
expect(transition(st, { type: "verify_passed", complete: true })).toEqual({ status: "satisfied", hasAsset: true });
|
||||
for (const from of ["empty", "reserved", "downloading", "verifying", "satisfied", "upgrade_pending"] as const)
|
||||
expect(canTransition(s(from), { type: "manual_verify", reason: "x" }), from).toBe(false);
|
||||
});
|
||||
it("部分覆盖回到 empty 但记住已有资产", () => {
|
||||
expect(transition(s("verifying"), { type: "verify_passed", complete: false })).toEqual({
|
||||
status: "empty",
|
||||
|
||||
Reference in new issue
Block a user