feat(campaign): govern attachment reuse

This commit is contained in:
2026-08-20 05:20:07 +02:00
parent f4fe534ee1
commit 112ef9dc31
16 changed files with 705 additions and 2 deletions
@@ -158,6 +158,9 @@ export default function ReviewSendPage({
);
const validation = asRecord(version?.validation_summary);
const build = asRecord(version?.build_summary);
const attachmentReuse = asRecord(build.attachment_reuse);
const attachmentReusePolicy = asRecord(attachmentReuse.policy);
const attachmentReuseFindings = asArray(attachmentReuse.findings).map(asRecord);
const residualFileDisposition = asRecord(build.residual_file_disposition);
const residualFileRecipient = asRecord(residualFileDisposition.recipient);
const printOutput = asRecord(build.print_output);
@@ -1504,6 +1507,29 @@ export default function ReviewSendPage({
</DescriptionList>
</div>
)}
{hasBuild && Object.keys(attachmentReuse).length > 0 && (
<div className="review-flow-data-section" data-attachment-reuse-policy>
<h3>Attachment reuse policy</h3>
<DescriptionList variant="inline">
<div><dt>Action</dt><dd>{humanize(String(attachmentReusePolicy.action ?? "allow"))}</dd></div>
<div><dt>Allowed boundary</dt><dd>{humanize(String(attachmentReusePolicy.allow_within ?? "none"))}</dd></div>
<div><dt>Repeated files</dt><dd>{String(attachmentReuse.duplicate_file_count ?? 0)}</dd></div>
<div><dt>Allowed</dt><dd>{String(attachmentReuse.allowed_file_count ?? 0)}</dd></div>
<div><dt>Policy findings</dt><dd>{String(attachmentReuse.violation_file_count ?? 0)}</dd></div>
<div><dt>Affected messages</dt><dd>{String(attachmentReuse.affected_message_count ?? 0)}</dd></div>
</DescriptionList>
{attachmentReuseFindings.length > 0 && (
<ul className="small-note">
{attachmentReuseFindings.slice(0, 10).map((finding) => (
<li key={String(finding.file_fingerprint)}>
{String(finding.file_name ?? "Attachment")} · {String(finding.use_count ?? 0)} uses · {humanize(String(finding.disposition ?? "allowed"))}
</li>
))}
</ul>
)}
{attachmentReuseFindings.length > 10 && <p className="muted small-note">Showing 10 of {attachmentReuseFindings.length} repeated files.</p>}
</div>
)}
{getText(printOutput, "render_id") && (
<div className="review-flow-data-section">
<div className="page-heading split">