Skip to article
Documentation

src/features/reviews/permissions.ts

Linked repository file from this build.

import { can, canAccessReview } from "@/lib/auth/scope";
import { sameActor } from "@/lib/auth/actor";
import { hasOpenStoredFindings } from "@/programs/snap-negative/validation";
import type { SnapReview } from "@/programs/snap-negative/types";
import type { Actor } from "./types";

/** Review rules that depend on both the role and the review state. The UI and execute share them. */
export function canEdit(review: SnapReview, actor: Actor): boolean {
  if (!canAccessReview(actor, review)) return false;
  return (
    actor.role === "examiner" && (review.state === "new_active" || review.state === "needs_changes")
  );
}

export function canAddNote(actor: Actor): boolean {
  return can(actor, "addNotes");
}

export function canUpdateNote(review: SnapReview, actor: Actor, noteId: string): boolean {
  if (!canAddNote(actor)) return false;
  const note = review.notes.find((entry) => entry.id === noteId);
  if (!note) return false;
  const kind = note.kind ?? "ordinary";
  if (sameActor(note.actor, actor)) return true;
  if (can(actor, "seniorReview") && kind === "ordinary") return true;
  return false;
}

export function canRefuseFinding(actor: Actor): boolean {
  return can(actor, "seniorReview");
}

export function canSubmitPolicyDecision(review: SnapReview, actor: Actor): boolean {
  return actor.role === "pec" && review.state === "awaiting_pec_approval";
}

export function openFindingsBlockApproval(review: SnapReview): boolean {
  return hasOpenStoredFindings(review);
}