fix(rectification): enforce trusted result identity and preserve receipt provenance
Unify minute and block cache identity, keep unverifiable historical results read-only across server tools and write entrypoints, and aggregate completed receipt sources chronologically through a compatible function migration. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,7 @@ const acceptSchema = z.object({
|
||||
function errorResponse(error: unknown) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
const known = [
|
||||
["result_identity_read_only", 409, "按旧算法产出,暂不能采用"],
|
||||
["agentic_rectification_candidate_not_found", 404, "候选记录不存在或已过期"],
|
||||
["agentic_rectification_candidate_expired", 409, "候选结果已过期,请重新比较"],
|
||||
["agentic_rectification_candidate_selection_blocked", 409, "当前还不能采用候选"],
|
||||
@@ -114,6 +115,8 @@ export async function POST(request: Request, context: RouteContext) {
|
||||
const { publicDecisionFields } = await import(
|
||||
"@/lib/rectification-agentic/core/rectification-decision"
|
||||
);
|
||||
const { assertV9ResultWritable } = await import("@/lib/rectification-agentic/v9/result-identity");
|
||||
await assertV9ResultWritable(accounting, user.id, caseId, parsed.data.resultId);
|
||||
const dossier = await loadV9CaseDossier(accounting, user.id, caseId);
|
||||
const decision = decideFromDossier(dossier, {
|
||||
currentEvidenceFingerprint: evidenceLedgerFingerprint(dossier.evidence),
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
listV10ConversationFocuses,
|
||||
} from "@/lib/rectification-agentic/v9/tool-service";
|
||||
import { ensureNonTerminalTurnExit } from "@/lib/rectification-agentic/v9/answer-choice";
|
||||
import { dossierResponse } from "@/lib/rectification-agentic/v9/case-dossier-response";
|
||||
import { dossierResponseWithIdentity } from "@/lib/rectification-agentic/v9/case-dossier-response";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
|
||||
@@ -77,7 +77,7 @@ export async function POST(request: Request, context: RouteContext) {
|
||||
const listed = await listV10ConversationFocuses(accounting, user.id, caseId);
|
||||
return NextResponse.json({
|
||||
ok: true,
|
||||
...dossierResponse(dossier, receipts, skillIdentity, { listed }),
|
||||
...await dossierResponseWithIdentity(dossier, receipts, skillIdentity, { listed }),
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof RectificationToolServiceError) {
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
listV10ConversationFocuses,
|
||||
safeToolErrorCode,
|
||||
} from "@/lib/rectification-agentic/v9/tool-service";
|
||||
import { dossierResponse } from "@/lib/rectification-agentic/v9/case-dossier-response";
|
||||
import { dossierResponseWithIdentity } from "@/lib/rectification-agentic/v9/case-dossier-response";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
|
||||
@@ -96,7 +96,7 @@ export async function GET(request: Request, context: RouteContext) {
|
||||
}),
|
||||
);
|
||||
const listed = await listV10ConversationFocuses(accounting, user.id, caseId);
|
||||
return NextResponse.json(dossierResponse(dossier, receipts, skillIdentity, { fullDetail, listed }));
|
||||
return NextResponse.json(await dossierResponseWithIdentity(dossier, receipts, skillIdentity, { fullDetail, listed }));
|
||||
} catch (error) {
|
||||
if (error instanceof RectificationToolServiceError) {
|
||||
const message = error.message;
|
||||
|
||||
Reference in New Issue
Block a user