Guardian-Agent / artifacts /api-server /src /lib /scan-pipeline.ts
Prince9868's picture
Hackathon submission: Guardian OpenEnv
5743bc2
Raw
History Blame Contribute Delete
3.36 kB
import { buildScanCopilot } from "./ai-copilot";
import type { CheckoutAnalysis } from "./checkout-analysis";
type ScanTrustRating = {
score?: number;
tier?: string;
} | null | undefined;
type ScanReportLike = CheckoutAnalysis & {
domain?: string;
url?: string;
[key: string]: any;
};
export function mergeScanReports(base: CheckoutAnalysis, ai: Record<string, any> | null | undefined, domain: string, url: string): ScanReportLike {
const merged: ScanReportLike = {
...base,
...ai,
domain,
url,
falseUrgency: {
...base.falseUrgency,
...ai?.falseUrgency,
},
falseScarcity: {
...base.falseScarcity,
...ai?.falseScarcity,
},
confirmShaming: {
...base.confirmShaming,
...ai?.confirmShaming,
},
hiddenFees: {
...base.hiddenFees,
...ai?.hiddenFees,
feeItems:
Array.isArray(ai?.hiddenFees?.feeItems) && ai.hiddenFees.feeItems.length > 0
? ai.hiddenFees.feeItems
: base.hiddenFees?.feeItems ?? [],
},
preCheckedAddOns: {
...base.preCheckedAddOns,
...ai?.preCheckedAddOns,
addOnLabels:
Array.isArray(ai?.preCheckedAddOns?.addOnLabels) && ai.preCheckedAddOns.addOnLabels.length > 0
? ai.preCheckedAddOns.addOnLabels
: base.preCheckedAddOns?.addOnLabels ?? [],
},
misdirection: {
...base.misdirection,
...ai?.misdirection,
},
};
const totalPatternsDetected = countDetectedPatterns(merged);
return {
...merged,
totalPatternsDetected,
trustScore:
typeof merged.trustScore === "number"
? merged.trustScore
: Math.max(20, 92 - totalPatternsDetected * 12),
summary:
typeof merged.summary === "string" && merged.summary.trim()
? merged.summary
: base.summary,
};
}
export function countDetectedPatterns(report: ScanReportLike): number {
return [
report.falseUrgency?.detected,
report.falseScarcity?.detected,
report.confirmShaming?.detected,
report.hiddenFees?.detected,
report.preCheckedAddOns?.detected,
report.misdirection?.detected,
].filter(Boolean).length;
}
export function buildScanArtifacts(input: {
domain: string;
url: string;
pageText?: string;
baseAnalysis: CheckoutAnalysis;
aiReport?: Record<string, any> | null;
trustRating?: ScanTrustRating;
}) {
const darkPatternReport = input.aiReport
? mergeScanReports(input.baseAnalysis, input.aiReport, input.domain, input.url)
: {
...input.baseAnalysis,
domain: input.domain,
url: input.url,
};
const totalPatternsDetected = countDetectedPatterns(darkPatternReport);
const hiddenFeesTotal = darkPatternReport.hiddenFees?.totalExtra ?? null;
const trustScore =
typeof darkPatternReport.trustScore === "number"
? darkPatternReport.trustScore
: input.trustRating?.score ?? 50;
return {
darkPatternReport: {
...darkPatternReport,
trustScore,
totalPatternsDetected,
},
totalPatternsDetected,
hiddenFeesTotal,
aiCopilot: buildScanCopilot({
domain: input.domain,
url: input.url,
pageText: input.pageText,
darkPatternReport: {
...darkPatternReport,
trustScore,
totalPatternsDetected,
},
trustRating: input.trustRating,
}),
};
}