feat: complete catalog sensitivity enhancements
This commit is contained in:
@@ -20,6 +20,26 @@ interface Props {
|
||||
onSaved: (columns: CatalogColumn[]) => void;
|
||||
}
|
||||
|
||||
function sensitivityReasonFor(
|
||||
suggestion: SensitivityReviewItem,
|
||||
sensitive: boolean,
|
||||
): string | null {
|
||||
if (!sensitive) return null;
|
||||
if (suggestion.assessment !== "sensitive") {
|
||||
return "Marked sensitive during human review despite a non-sensitive local assessment.";
|
||||
}
|
||||
const evidence = suggestion.evidence.map((item) => {
|
||||
const confidence = item.confidence === undefined
|
||||
? ""
|
||||
: `, confidence ${Math.round(item.confidence * 100)}%`;
|
||||
return item.label
|
||||
? `${item.label} (${item.ruleId}${confidence})`
|
||||
: `${item.ruleId}${confidence}`;
|
||||
}).join(", ");
|
||||
const coverage = suggestion.coverage.replaceAll("_", " ");
|
||||
return `Local assessment: sensitive. Evidence: ${evidence || "policy match"}. Coverage: ${coverage}; observed values: ${suggestion.observedValues}.`;
|
||||
}
|
||||
|
||||
export function SensitiveDataReviewDrawer({
|
||||
open,
|
||||
databaseId,
|
||||
@@ -75,17 +95,22 @@ export function SensitiveDataReviewDrawer({
|
||||
const save = async () => {
|
||||
if (!databaseId || changed.length === 0) return;
|
||||
setSaving(true);
|
||||
const results = await Promise.allSettled(changed.map((suggestion) => (
|
||||
updateCatalogColumnSensitive(
|
||||
databaseId,
|
||||
suggestion.tableId,
|
||||
suggestion.columnId,
|
||||
suggestion.version,
|
||||
drafts[suggestion.columnId]!,
|
||||
)
|
||||
)));
|
||||
const saved = results.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
|
||||
const failed = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
||||
const saved: CatalogColumn[] = [];
|
||||
const failed: unknown[] = [];
|
||||
for (const suggestion of changed) {
|
||||
try {
|
||||
saved.push(await updateCatalogColumnSensitive(
|
||||
databaseId,
|
||||
suggestion.tableId,
|
||||
suggestion.columnId,
|
||||
suggestion.version,
|
||||
drafts[suggestion.columnId]!,
|
||||
sensitivityReasonFor(suggestion, drafts[suggestion.columnId]!),
|
||||
));
|
||||
} catch (error) {
|
||||
failed.push(error);
|
||||
}
|
||||
}
|
||||
if (saved.length > 0) onSaved(saved);
|
||||
if (failed.length > 0) {
|
||||
toast.error(`${failed.length} sensitive flag${failed.length === 1 ? "" : "s"} could not be saved: ${apiErrorMessage(failed[0])}`);
|
||||
@@ -115,7 +140,7 @@ export function SensitiveDataReviewDrawer({
|
||||
<div className="flex gap-2">
|
||||
<Button type="button" variant="outline" disabled={saving} onClick={close}>Cancel</Button>
|
||||
<Button type="button" disabled={!canManage || saving || changed.length === 0} onClick={() => void save()}>
|
||||
<Save />{saving ? "Saving…" : `Save ${changed.length}`}
|
||||
<Save />{saving ? "Saving…" : `Save all ${changed.length} change${changed.length === 1 ? "" : "s"}`}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user