fix(campaigns,ui): remove admin from campaign-from-threat-actor gate, bump red/blue label saturation
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled

- ThreatActorDetailPage wrongly let admins see/click 'Generate Campaign' —
  the backend already rejects admin there (require_any_role_strict), but
  the button was still shown, exposing a dead-end action. Now matches
  CampaignsPage's own admin-excluded gate.
- Red/blue team badges (role pills, team tabs, assignee controls, test
  state badges) bumped from -400 text/-900/50 bg to -500 text/-900/70 bg
  for more saturated, readable team colors.
This commit is contained in:
kitos
2026-07-20 16:18:27 +02:00
parent e4f768962f
commit 06c913955c
5 changed files with 12 additions and 13 deletions
@@ -24,8 +24,8 @@ interface Props {
}
const SIDE_STYLE = {
red: "border-red-500/40 bg-red-900/20 text-red-400 hover:bg-red-900/40",
blue: "border-blue-500/40 bg-blue-900/20 text-blue-400 hover:bg-blue-900/40",
red: "border-red-500/40 bg-red-900/20 text-red-500 hover:bg-red-900/40",
blue: "border-blue-500/40 bg-blue-900/20 text-blue-500 hover:bg-blue-900/40",
};
const ELIGIBLE_ROLES: Record<"operator" | "reviewer", Record<"red" | "blue", string[]>> = {
@@ -43,8 +43,8 @@ const TABS: { key: TabKey; label: string; icon: React.ReactNode }[] = [
];
const TAB_COLORS: Record<TabKey, string> = {
red: "border-red-500 text-red-400",
blue: "border-blue-500 text-blue-400",
red: "border-red-500 text-red-500",
blue: "border-blue-500 text-blue-500",
summary: "border-cyan-500 text-cyan-400",
timeline: "border-gray-500 text-gray-400",
};
@@ -52,13 +52,13 @@ const STATE_INDEX: Record<TestState, number> = {
const STATE_BADGE: Record<TestState, string> = {
draft: "bg-gray-800/50 text-gray-400 border-gray-600/30",
red_executing: "bg-red-900/50 text-red-400 border-red-500/30",
red_executing: "bg-red-900/70 text-red-500 border-red-500/40",
red_review: "bg-amber-900/50 text-amber-400 border-amber-500/30",
blue_evaluating: "bg-blue-900/50 text-blue-400 border-blue-500/30",
blue_evaluating: "bg-blue-900/70 text-blue-500 border-blue-500/40",
blue_review: "bg-purple-900/50 text-purple-400 border-purple-500/30",
in_review: "bg-blue-900/50 text-blue-400 border-blue-500/30",
validated: "bg-green-900/50 text-green-400 border-green-500/30",
rejected: "bg-red-900/50 text-red-400 border-red-500/30",
rejected: "bg-red-900/70 text-red-500 border-red-500/40",
disputed: "bg-amber-900/50 text-amber-400 border-amber-500/30",
};
+1 -2
View File
@@ -107,8 +107,7 @@ export default function ThreatActorDetailPage() {
const queryClient = useQueryClient();
const { user } = useAuth();
const canGenerate =
user?.role === "admin" || user?.role === "red_lead" || user?.role === "blue_lead";
const canGenerate = user?.role === "red_lead" || user?.role === "blue_lead";
// ── Campaign generation modal state ─────────────────────────────
const [showCampaignModal, setShowCampaignModal] = useState(false);
+4 -4
View File
@@ -33,10 +33,10 @@ const ROLES = [
const roleBadgeColors: Record<string, string> = {
admin: "bg-purple-900/50 text-purple-400 border-purple-500/30",
red_tech: "bg-red-900/50 text-red-400 border-red-500/30",
blue_tech: "bg-blue-900/50 text-blue-400 border-blue-500/30",
red_lead: "bg-red-900/50 text-red-400 border-red-500/30",
blue_lead: "bg-blue-900/50 text-blue-400 border-blue-500/30",
red_tech: "bg-red-900/70 text-red-500 border-red-500/40",
blue_tech: "bg-blue-900/70 text-blue-500 border-blue-500/40",
red_lead: "bg-red-900/70 text-red-500 border-red-500/40",
blue_lead: "bg-blue-900/70 text-blue-500 border-blue-500/40",
manager: "bg-amber-900/50 text-amber-400 border-amber-500/30",
viewer: "bg-gray-800/50 text-gray-400 border-gray-600/30",
};