fix(tests): lock editing for operators until timer starts
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
red_tech can only edit procedure/tool/summary when the test is in red_executing state (after pressing Start Execution). In draft state they see a read-only view and an orange hint 'Press Start Execution to begin editing — the timer must be running first.' blue_tech can only edit when blue_work_started_at is set (after pressing Start Evaluation). Before that they see an indigo hint 'Press Start Evaluation to begin editing — pick up the test first.' red_lead, blue_lead and admin are unaffected — they retain full edit access in all applicable states including draft.
This commit is contained in:
@@ -118,18 +118,46 @@ export default function TeamTabs({
|
||||
enabled: !!test.technique_mitre_id,
|
||||
});
|
||||
|
||||
// Leads and admins can edit during both draft and executing phases.
|
||||
// Operators (red_tech) may only edit once execution has started —
|
||||
// the timer must be running before they can document the attack.
|
||||
const canEditRed =
|
||||
RED_EDITABLE_STATES.includes(test.state) &&
|
||||
(role === "red_tech" || role === "red_lead" || role === "admin");
|
||||
(test.state === "red_executing" &&
|
||||
(role === "red_tech" || role === "red_lead" || role === "admin")) ||
|
||||
(test.state === "draft" && (role === "red_lead" || role === "admin"));
|
||||
|
||||
// Blue operators may only edit after they explicitly pick up the test
|
||||
// (Start Evaluation pressed → blue_work_started_at is set).
|
||||
// Blue leads and admins can edit at any point during blue_evaluating.
|
||||
const canEditBlue =
|
||||
BLUE_EDITABLE_STATES.includes(test.state) &&
|
||||
(role === "blue_tech" || role === "blue_lead" || role === "admin");
|
||||
((role === "blue_lead" || role === "admin") ||
|
||||
(role === "blue_tech" && !!test.blue_work_started_at));
|
||||
|
||||
// Hint messages shown to operators when editing is locked
|
||||
const redLockedHint =
|
||||
test.state === "draft" && role === "red_tech"
|
||||
? "Press Start Execution to begin editing — the timer must be running first."
|
||||
: null;
|
||||
|
||||
const blueLockedHint =
|
||||
BLUE_EDITABLE_STATES.includes(test.state) &&
|
||||
role === "blue_tech" &&
|
||||
!test.blue_work_started_at
|
||||
? "Press Start Evaluation to begin editing — pick up the test first."
|
||||
: null;
|
||||
|
||||
// ── Red Team Tab ─────────────────────────────────────────────────
|
||||
|
||||
const renderRedTab = () => (
|
||||
<div className="space-y-6">
|
||||
{/* Locked hint for red_tech in draft state */}
|
||||
{redLockedHint && (
|
||||
<div className="flex items-center gap-2 rounded-lg border border-orange-500/30 bg-orange-500/5 px-4 py-3 text-sm text-orange-400">
|
||||
<span className="text-base">⏱</span>
|
||||
{redLockedHint}
|
||||
</div>
|
||||
)}
|
||||
{/* Procedure */}
|
||||
<div>
|
||||
<label className="mb-1.5 block text-sm font-medium text-gray-300">
|
||||
@@ -262,6 +290,13 @@ export default function TeamTabs({
|
||||
|
||||
const renderBlueTab = () => (
|
||||
<div className="space-y-6">
|
||||
{/* Locked hint for blue_tech before Start Evaluation */}
|
||||
{blueLockedHint && (
|
||||
<div className="flex items-center gap-2 rounded-lg border border-indigo-500/30 bg-indigo-500/5 px-4 py-3 text-sm text-indigo-400">
|
||||
<span className="text-base">⏱</span>
|
||||
{blueLockedHint}
|
||||
</div>
|
||||
)}
|
||||
{/* Detection Result */}
|
||||
<div>
|
||||
<label className="mb-2 block text-sm font-medium text-gray-300">
|
||||
|
||||
Reference in New Issue
Block a user