export type ReportSecurityErrorCode =
  | "non-loopback-host"
  | "invalid-capability-token"
  | "csrf-violation"
  | "same-origin-violation"
  | "path-traversal"
  | "symlink-escape"
  | "absolute-path"
  | "file-url-path"
  | "external-write-target";

export class ReportSecurityError extends Error {
  readonly code: ReportSecurityErrorCode;

  constructor(code: ReportSecurityErrorCode, message: string) {
    super(message);
    this.name = "ReportSecurityError";
    this.code = code;
  }
}

export class NonLoopbackHostError extends ReportSecurityError {
  constructor(host: string) {
    super("non-loopback-host", `report server host must be loopback-only: ${host}`);
    this.name = "NonLoopbackHostError";
  }
}

export class InvalidCapabilityTokenError extends ReportSecurityError {
  constructor() {
    super("invalid-capability-token", "missing or invalid report capability token");
    this.name = "InvalidCapabilityTokenError";
  }
}

export class CsrfViolationError extends ReportSecurityError {
  constructor() {
    super("csrf-violation", "missing or invalid CSRF token");
    this.name = "CsrfViolationError";
  }
}

export class SameOriginViolationError extends ReportSecurityError {
  constructor() {
    super("same-origin-violation", "cross-origin mutation request rejected");
    this.name = "SameOriginViolationError";
  }
}

export class PathTraversalError extends ReportSecurityError {
  constructor(path: string) {
    super("path-traversal", `artifact path escapes report root: ${path}`);
    this.name = "PathTraversalError";
  }
}

export class SymlinkEscapeError extends ReportSecurityError {
  constructor(path: string) {
    super("symlink-escape", `artifact path resolves outside report root: ${path}`);
    this.name = "SymlinkEscapeError";
  }
}

export class AbsolutePathError extends ReportSecurityError {
  constructor(path: string) {
    super("absolute-path", `absolute artifact paths are not allowed: ${path}`);
    this.name = "AbsolutePathError";
  }
}

export class FileUrlPathError extends ReportSecurityError {
  constructor(path: string) {
    super("file-url-path", `file URLs are not allowed for artifact paths: ${path}`);
    this.name = "FileUrlPathError";
  }
}

export class ExternalWriteTargetError extends ReportSecurityError {
  constructor(path: string) {
    super("external-write-target", `write target is outside report root: ${path}`);
    this.name = "ExternalWriteTargetError";
  }
}
