/**
 * Finite public projection contracts for the runs surface.
 *
 * The contracts intentionally expose only bounded enums, ISO timestamps, and
 * sanitized labels. They do not pass through provider IDs, command bodies,
 * matcher keys, audit IDs, local paths, tokens, or debug fragments.
 *
 * `runtimeTimeline` events on the run detail projection use the existing
 * runtimeTimelineContract so the redacted timeline pipeline stays single-source.
 */
export const RUN_PROJECTION_PUBLIC_SOURCE = "runs";
export const RUN_PROJECTION_STATUSES = [
    "queued",
    "running",
    "completed",
    "failed",
    "cancelled",
    "blocked-budget",
    "blocked-timeout",
    "blocked-concurrency",
];
export const RUN_PROJECTION_TONES = [
    "primary",
    "success",
    "warning",
    "destructive",
    "muted",
];
export const RUN_PROJECTION_SOURCE_MARKERS = [
    "local-sqlite-live",
    "local-sqlite-seed",
];
const MAX_PUBLIC_TITLE_LENGTH = 200;
const UNSAFE_PUBLIC_STRING_PATTERNS = [
    /\bsk-[A-Za-z0-9_-]{6,}\b/u,
    /\bsk-ant-[A-Za-z0-9_-]{6,}\b/u,
    /\bAIza[A-Za-z0-9_-]{8,}\b/u,
    /\bpt_lui_(?:sess_)?[A-Za-z0-9_-]{8,}\b/u,
    /\bBearer\s+[A-Za-z0-9._~-]{8,}\b/iu,
    /patchTrailLocalHandoff=/iu,
    /-----BEGIN [A-Z ]*PRIVATE KEY-----/u,
    /\/Users\/[^\s]+/u,
    /[A-Za-z]:\\Users\\[^\s]+/u,
    /\.sqlite\b/iu,
    /\.db\b/iu,
];
/**
 * Trim or null out a UI-facing string. Rejects values that match an unsafe
 * sentinel pattern so we fail closed rather than emit something risky.
 */
export function readPublicTitle(value) {
    if (value === null || value === undefined)
        return null;
    const trimmed = value.trim();
    if (!trimmed)
        return null;
    if (trimmed.length > MAX_PUBLIC_TITLE_LENGTH)
        return null;
    for (const pattern of UNSAFE_PUBLIC_STRING_PATTERNS) {
        if (pattern.test(trimmed))
            return null;
    }
    return trimmed;
}
/**
 * Map a run status to a bounded UI tone enum.
 */
export function toneForRunStatus(status) {
    switch (status) {
        case "running":
        case "queued":
            return "primary";
        case "completed":
            return "success";
        case "failed":
            return "destructive";
        case "cancelled":
            return "muted";
        case "blocked-budget":
        case "blocked-timeout":
        case "blocked-concurrency":
            return "warning";
    }
}
export function isUnsafePublicString(value) {
    for (const pattern of UNSAFE_PUBLIC_STRING_PATTERNS) {
        if (pattern.test(value))
            return true;
    }
    return false;
}
