fix(report): stop listing reports via PostgREST JSON paths (BUG-574)
Staging PostgREST rejects the executiveSummary JSON-path alias, so GET /api/reports 500s. Persist a plain card_summary column from the Markdown excerpt instead. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -28,6 +28,7 @@ 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";
|
||||
import { sanitizedErrorReason } from "@/lib/safe-error-reason";
|
||||
import { isSupabaseConfigurationError } from "@/lib/supabase/config";
|
||||
import { createServerSupabaseClient } from "@/lib/supabase/server";
|
||||
|
||||
@@ -45,7 +46,7 @@ const REPORT_LIST_COLUMNS = [
|
||||
"failure_code",
|
||||
"created_at",
|
||||
"completed_at",
|
||||
"card_summary:report_document->executiveSummary->>summary",
|
||||
"card_summary",
|
||||
].join(",");
|
||||
|
||||
function sanitizedErrorCode(error: unknown): string {
|
||||
@@ -139,7 +140,7 @@ export async function GET() {
|
||||
{ status: 503 },
|
||||
);
|
||||
}
|
||||
console.error(`[reports] list failed reason=${sanitizedErrorCode(error)}`);
|
||||
console.error(`[reports] list failed reason=${sanitizedErrorReason(error)}`);
|
||||
return NextResponse.json(
|
||||
{ error: "报告列表暂时无法读取", code: REPORT_STABLE_CODES.generationFailed },
|
||||
{ status: 500 },
|
||||
|
||||
@@ -4,7 +4,10 @@ import {
|
||||
REPORT_DOCUMENT_V2_SCHEMA_VERSION,
|
||||
type ReportDocumentV2,
|
||||
} from "./personal-report-contract.ts";
|
||||
import { extractLongformSummary } from "./personal-report-longform-outline.ts";
|
||||
import {
|
||||
PERSONAL_REPORT_CARD_SUMMARY_MAX_CHARS,
|
||||
extractLongformSummary,
|
||||
} from "./personal-report-longform-outline.ts";
|
||||
import type { PersonalReportRecord } from "./personal-report-service-core.ts";
|
||||
|
||||
type CoverSkillSnapshot = Readonly<{
|
||||
@@ -52,7 +55,7 @@ function coverHouses(): ReportDocumentV2["charts"][number]["houses"] {
|
||||
}
|
||||
|
||||
export function buildLongformCoverDocument(input: LongformCoverInput): ReportDocumentV2 {
|
||||
const summary = extractLongformSummary(input.markdown);
|
||||
const summary = extractLongformSummary(input.markdown, PERSONAL_REPORT_CARD_SUMMARY_MAX_CHARS);
|
||||
const skillName = input.skillSnapshot?.name ?? input.report.skillName;
|
||||
const skillVersion = input.skillSnapshot?.version ?? input.report.skillVersion;
|
||||
const skillSnapshotSha256 = input.skillSnapshot?.sha256 ?? input.report.skillSnapshotSha256;
|
||||
|
||||
@@ -23,6 +23,9 @@ export type LongformOutline = Readonly<{
|
||||
const EAGER_H2 = /成品阅读导航|质量验收矩阵/;
|
||||
const SUMMARY_TITLE = /^(?:解读摘要|摘要)$/;
|
||||
|
||||
/** Dedicated `personal_reports.card_summary` column length. */
|
||||
export const PERSONAL_REPORT_CARD_SUMMARY_MAX_CHARS = 500;
|
||||
|
||||
export function slugifyHeading(title: string, used: Map<string, number>): string {
|
||||
const base = title
|
||||
.trim()
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Operational log reason for unknown catch values.
|
||||
*
|
||||
* PostgREST / supabase-js may throw a plain object with `code` and `hint`
|
||||
* instead of an Error instance. Never include message, details, or row data.
|
||||
*/
|
||||
export function sanitizedErrorReason(error: unknown): string {
|
||||
const record = error !== null && typeof error === "object"
|
||||
? error as Record<string, unknown>
|
||||
: null;
|
||||
const name = error instanceof Error && error.name.trim()
|
||||
? error.name.trim()
|
||||
: typeof record?.name === "string" && record.name.trim()
|
||||
? record.name.trim()
|
||||
: "UnknownError";
|
||||
const code = typeof record?.code === "string" ? record.code.trim() : "";
|
||||
const hint = typeof record?.hint === "string" ? record.hint.trim() : "";
|
||||
if (!code && !hint) return name;
|
||||
return `${name} code=${code || "none"} hint=${hint || "none"}`;
|
||||
}
|
||||
Reference in New Issue
Block a user