fix(report): load candidate ranges through a read-only RPC

Accepted profiles were selecting a revoked rectification table and failing the report before the engine ran. Degrade to a null window when that optional read fails.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-09-04 19:17:14 +08:00
co-authored by Cursor
parent 73a04e9970
commit 7baf230066
13 changed files with 602 additions and 84 deletions
+5 -30
View File
@@ -24,6 +24,7 @@ import {
type PersonalReportService,
} from "@/lib/personal-report-service";
import { createSupabasePersonalReportJobService } from "@/lib/personal-report-job-service";
import { loadReportCandidateRange } from "@/lib/report-candidate-range";
import { createAdminSupabaseClient } from "@/lib/supabase/admin";
import { authorizeUsage, completeUsage, releaseUsage } from "@/lib/consultation-billing";
import { FeaturePricingError, resolveFeaturePricing } from "@/lib/feature-pricing";
@@ -187,36 +188,10 @@ export async function POST(request: Request) {
const caseId = typeof profileRow.rectification_case_id === "string"
? profileRow.rectification_case_id
: null;
if (caseId) {
const { data, error } = await admin
.from("birth_time_rectification_cases")
.select("candidate_start,candidate_end")
.eq("id", caseId)
.eq("user_id", userId as string)
.in("status", ["confirmed", "completed"])
.maybeSingle();
if (error) throw error;
const row = data && typeof data === "object" ? data as Record<string, unknown> : null;
if (row && typeof row.candidate_start === "string" && typeof row.candidate_end === "string") {
return { startTime: row.candidate_start, endTime: row.candidate_end };
}
}
const { data, error } = await admin
.from("agentic_rectification_cases")
.select("candidate_range,updated_at")
.eq("user_id", userId as string)
.eq("status", "candidate_accepted")
.order("updated_at", { ascending: false })
.limit(1)
.maybeSingle();
if (error) throw error;
const row = data && typeof data === "object" ? data as Record<string, unknown> : null;
const range = row?.candidate_range && typeof row.candidate_range === "object"
? row.candidate_range as Record<string, unknown>
: null;
return range && typeof range.start_time === "string" && typeof range.end_time === "string"
? { startTime: range.start_time, endTime: range.end_time }
: null;
return loadReportCandidateRange(admin, {
userId: userId as string,
rectificationCaseId: caseId,
});
},
checkSessionOwned: async (sessionId) => {
const { data, error } = await supabase