fix(approvals): friendly case title (no 32-hex business_subject leaks)
Buyer-script audit showed queue row titles falling through to raw case-key hex when business_subject was empty / set to the case key itself. New friendlyCaseTitle helper: - prefer display_name if not machine-shaped - prefer business_subject if not machine-shaped - else 'Case in <step name>' - else 'Untitled case' isMachineId catches 20+-char hex AND process_<timestamp> pattern.
This commit is contained in:
@@ -88,11 +88,25 @@ if (await btn.count() > 0) {
|
|||||||
await p.waitForTimeout(3000);
|
await p.waitForTimeout(3000);
|
||||||
}
|
}
|
||||||
const tail = (await p.locator("body").innerText()).toLowerCase();
|
const tail = (await p.locator("body").innerText()).toLowerCase();
|
||||||
const tailFindings = FORBIDDEN_PATTERNS.filter((f) => f.re.test(tail)).map((f) => f.name).slice(0, 3);
|
const tailFindings = FORBIDDEN_PATTERNS.filter((f) => f.re.test(tail)).map((f) => ({ name: f.name, sample: (tail.match(f.re) || [""])[0].slice(0, 80) })).slice(0, 3);
|
||||||
|
// Find where the 32-hex actually lives — was it the case-row title, the
|
||||||
|
// active-step body, the toast, or something else?
|
||||||
|
const hex32Loc = await p.evaluate(() => {
|
||||||
|
const re = /[a-f0-9]{32}/i;
|
||||||
|
const out = [];
|
||||||
|
document.querySelectorAll("*").forEach((el) => {
|
||||||
|
if (el.children.length > 0) return;
|
||||||
|
const t = (el.textContent || "").trim();
|
||||||
|
if (t && re.test(t)) {
|
||||||
|
out.push({ tag: el.tagName, cls: (el.className || "").toString().slice(0, 60), text: t.slice(0, 120) });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return out.slice(0, 5);
|
||||||
|
});
|
||||||
record(
|
record(
|
||||||
"buyer_approvals_action_click_no_embarrassing_copy",
|
"buyer_approvals_action_click_no_embarrassing_copy",
|
||||||
tailFindings.length === 0,
|
tailFindings.length === 0,
|
||||||
tailFindings.length ? `LEAK: ${tailFindings.join(", ")} (was disabled? ${isDisabled})` : `clean (disabled? ${isDisabled})`
|
tailFindings.length ? `LEAK [${tailFindings.map((f) => `${f.name}=${f.sample}`).join(", ")}] (disabled? ${isDisabled}) | sites: ${hex32Loc.map((h) => `${h.tag}.${h.cls}:"${h.text}"`).join(" || ")}` : `clean (disabled? ${isDisabled})`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,21 @@ function ageLabel(item: WorkItem): string {
|
|||||||
return `${Math.floor(days / 30)} mo`;
|
return `${Math.floor(days / 30)} mo`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isMachineId(s?: string | null): boolean {
|
||||||
|
if (!s) return true;
|
||||||
|
return /^[a-f0-9]{20,}$/i.test(s) || /^process_\d{10,}$/.test(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
function friendlyCaseTitle(item: WorkItem): string {
|
||||||
|
const display = (item as any).display_name as string | undefined;
|
||||||
|
const subject = item.business_subject;
|
||||||
|
if (display && !isMachineId(display)) return display;
|
||||||
|
if (subject && !isMachineId(subject)) return subject;
|
||||||
|
const stepName = item.active_step_display_name || item.next_action;
|
||||||
|
if (stepName) return `Case in ${stepName}`;
|
||||||
|
return "Untitled case";
|
||||||
|
}
|
||||||
|
|
||||||
export default function Approvals() {
|
export default function Approvals() {
|
||||||
const userEmail = useApp((s) => s.userEmail);
|
const userEmail = useApp((s) => s.userEmail);
|
||||||
const actor = useApp((s) => s.actor);
|
const actor = useApp((s) => s.actor);
|
||||||
@@ -145,7 +160,7 @@ export default function Approvals() {
|
|||||||
onClick={() => setActiveKey(it.transaction_id)}
|
onClick={() => setActiveKey(it.transaction_id)}
|
||||||
>
|
>
|
||||||
<div className="approvals-row-head">
|
<div className="approvals-row-head">
|
||||||
<span className="approvals-row-title">{(it as any).display_name || it.business_subject || "Untitled case"}</span>
|
<span className="approvals-row-title">{friendlyCaseTitle(it)}</span>
|
||||||
<span className="approvals-row-age">{it.age_label}</span>
|
<span className="approvals-row-age">{it.age_label}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="approvals-row-meta">
|
<div className="approvals-row-meta">
|
||||||
|
|||||||
Reference in New Issue
Block a user