import type { Pagination } from '../pagination/index.js'; export const AI_AGENT_STATUSES = ['active', 'disabled'] as const; export const REVIEW_POLICY_NAME_MAX_LENGTH = 120; export const REVIEW_POLICY_PROMPT_MAX_LENGTH = 10000; // Display name of the Superblocks-managed built-in security scan. One per organization. export const BUILT_IN_SECURITY_SCAN_NAME = 'Superblocks Security Scan'; // Display name of the Superblocks-managed security agent. One per organization; its prompt is owned // by the platform, so admins can only enable it and choose its mode. export const SUPERBLOCKS_SECURITY_AGENT_NAME = 'Superblocks Security Agent'; export const REVIEW_POLICY_TYPES = ['built_in_security_scan', 'security_agent'] as const; export const REVIEW_POLICY_SOURCES = ['admin_configured', 'superblocks_managed'] as const; export const REVIEW_POLICY_TRIGGERS = ['before_deploy', 'after_checkpoint', 'manual'] as const; export const REVIEW_POLICY_EXECUTION_CONTEXTS = [ 'edit_mode_app', 'superblocks_sabs_built_assets', 'superblocks_sabs_dependency_metadata', 'superblocks_sabs_source_snapshot' ] as const; export const REVIEW_POLICY_RUNTIMES = ['superblocks_dev_server_agent', 'superblocks_sabs'] as const; export const REVIEW_POLICY_MODES = ['advisory', 'blocking'] as const; export const REVIEW_POLICY_RUNNER_TYPES = ['built_in_security_scan', 'llm_security_agent'] as const; export const REVIEW_FINDING_SOURCE_PHASES = ['built_asset', 'dependency', 'edit_mode_app', 'iac', 'image', 'source'] as const; export const REVIEW_FINDING_CATEGORIES = [ 'external_policy', 'misconfiguration', 'security_agent', 'secret', 'sensitive_data', 'static_analysis', 'vulnerability' ] as const; // Severity and confidence order is semantically meaningful from strongest to weakest. export const REVIEW_FINDING_SEVERITIES = ['critical', 'high', 'medium', 'low', 'info'] as const; /** Severities that pause publish for "Publish anyway" in any policy mode. Info auto-publishes. */ export const ADVISORY_HOLD_FINDING_SEVERITIES = ['critical', 'high', 'medium', 'low'] as const; /** Severities that hard-block publish when a policy is in blocking mode (ENG-5334 / APPS-5406). */ export const BLOCKING_FINDING_SEVERITIES = ['critical', 'high'] as const; export const REVIEW_FINDING_CONFIDENCES = ['high', 'medium', 'low'] as const; export const REVIEW_FINDING_SUPPRESSION_STATUSES = ['active', 'expired', 'revoked'] as const; // Lifecycle ordering is semantically meaningful; matches AiAgentRun status sequence with review-specific states. export const REVIEW_RUN_STATUSES = [ 'queued', 'running', 'passed', 'findings', 'blocked', 'errored', 'timed_out', 'canceled', 'stale' ] as const; // Lifecycle ordering is semantically meaningful. export const REVIEW_RUN_DECISIONS = ['allowed', 'advisory_allowed', 'blocked', 'error_blocked', 'not_applicable'] as const; export const REVIEW_RUN_TRIGGERED_BYS = ['system', 'user'] as const; export type AiAgentStatus = (typeof AI_AGENT_STATUSES)[number]; export type ReviewPolicyStatus = AiAgentStatus; export type ReviewPolicyType = (typeof REVIEW_POLICY_TYPES)[number]; export type ReviewPolicySource = (typeof REVIEW_POLICY_SOURCES)[number]; export type ReviewPolicyTrigger = (typeof REVIEW_POLICY_TRIGGERS)[number]; export type ReviewPolicyExecutionContext = (typeof REVIEW_POLICY_EXECUTION_CONTEXTS)[number]; export type ReviewPolicyRuntime = (typeof REVIEW_POLICY_RUNTIMES)[number]; export type ReviewPolicyMode = (typeof REVIEW_POLICY_MODES)[number]; export type ReviewPolicyRunnerType = (typeof REVIEW_POLICY_RUNNER_TYPES)[number]; export type ReviewFindingSourcePhase = (typeof REVIEW_FINDING_SOURCE_PHASES)[number]; export type ReviewFindingCategory = (typeof REVIEW_FINDING_CATEGORIES)[number]; export type ReviewFindingSeverity = (typeof REVIEW_FINDING_SEVERITIES)[number]; export type AdvisoryHoldFindingSeverity = (typeof ADVISORY_HOLD_FINDING_SEVERITIES)[number]; export type BlockingFindingSeverity = (typeof BLOCKING_FINDING_SEVERITIES)[number]; export type ReviewFindingConfidence = (typeof REVIEW_FINDING_CONFIDENCES)[number]; /** True when a finding severity pauses publish until the user acknowledges with "Publish anyway". */ export function isAdvisoryHoldFindingSeverity(severity: string): severity is AdvisoryHoldFindingSeverity { return (ADVISORY_HOLD_FINDING_SEVERITIES as readonly string[]).includes(severity); } /** True when a finding severity hard-blocks publish under blocking-mode policy gates. */ export function isBlockingFindingSeverity(severity: string): severity is BlockingFindingSeverity { return (BLOCKING_FINDING_SEVERITIES as readonly string[]).includes(severity); } export type ReviewFindingSuppressionStatus = (typeof REVIEW_FINDING_SUPPRESSION_STATUSES)[number]; export type ReviewRunStatus = (typeof REVIEW_RUN_STATUSES)[number]; export type ReviewRunDecision = (typeof REVIEW_RUN_DECISIONS)[number]; export type ReviewRunTriggeredBy = (typeof REVIEW_RUN_TRIGGERED_BYS)[number]; export type ReviewPolicyScopeType = 'all_apps' | 'limited'; export type ReviewPolicyScopeDto = { type: 'all_apps' } | { type: 'limited'; applicationIds: string[] }; export type ReviewPolicyScopeInput = { type: 'all_apps' } | { type: 'limited'; applicationIds: string[] }; export interface ReviewPolicyLastRunDto { id: string; status: ReviewRunStatus; created: string; findingsCount: number; } // Lifecycle stages for the Policies page strip/table. Derived from // `review_policy_version.trigger` today; not a persisted column. -> TODO add this as a persistent // column when we actually want to implement this functionality export const REVIEW_POLICY_STAGES = ['development', 'publish', 'production'] as const; export type ReviewPolicyStage = (typeof REVIEW_POLICY_STAGES)[number]; // Product domain for a policy (security scanners/agents vs future kinds). // Only `security` ships today; extend this allowlist when accessibility (etc.) lands. export const REVIEW_POLICY_DOMAINS = ['security'] as const; export type ReviewPolicyDomain = (typeof REVIEW_POLICY_DOMAINS)[number]; /** * Maps a concrete policy type onto its product domain. Every type today is * security; add branches (and REVIEW_POLICY_DOMAINS values) when non-security * policies ship. Do not invent UI-only domain labels. */ export function reviewPolicyDomainForType(_policyType: ReviewPolicyType): ReviewPolicyDomain { return 'security'; } export interface ReviewPolicyDto { id: string; organizationId: string; aiAgentId: string; activeVersionId: string; versionNumber: number; policyType: ReviewPolicyType; source: ReviewPolicySource; name: string; status: AiAgentStatus; mode: ReviewPolicyMode; scope: ReviewPolicyScopeDto; stage: ReviewPolicyStage; // Derived for the wire today (not a DB column). See reviewPolicyDomainForType. // maybe replace with col in the future as we add more domain: ReviewPolicyDomain; lastRun: ReviewPolicyLastRunDto | null; freshPendingApprovalRunCount: number; createdBy: string | null; created: string; } export interface ReviewPolicyDetailDto extends ReviewPolicyDto { prompt: string; } export interface ReviewPolicyRunDto { id: string; applicationId: string; applicationName: string | null; applicationCommitId: string; applicationCommitMessage: string | null; policyId: string; policyName: string; policyVersionNumber: number; findingsCount: number; profileId: string; status: ReviewRunStatus; decision: ReviewRunDecision | null; decisionReason: string | null; hasFreshPendingApproval: boolean; triggeredBy: ReviewRunTriggeredBy | null; triggeringUserName: string | null; startedAt: string | null; completedAt: string | null; created: string; errorCode: string | null; errorMessage: string | null; } export interface ReviewFindingDto { id: string; sourceTool: string; sourceRuleId: string | null; sourcePolicyId: string | null; sourcePhase: ReviewFindingSourcePhase | null; category: ReviewFindingCategory; findingType: string | null; severity: ReviewFindingSeverity; confidence: ReviewFindingConfidence | null; blocking: boolean; blockingReason: string | null; title: string; humanSummary: string | null; technicalSummary: string | null; evidence: Record; locations: unknown[]; remediationHint: Record; clarkRemediable: boolean; adminOnly: boolean; created: string; } export interface ReviewPolicyRunFindingAggregatesDto { blockingCount: number; nonBlockingCount: number; severityCounts: Partial>; } export interface ReviewPolicyRunReportDto { aggregates: ReviewPolicyRunFindingAggregatesDto; findings: Pagination; policy: ReviewPolicyDto; run: ReviewPolicyRunDto; } // App-scoped, server-paged findings for one policy run (publish-tab table). export interface ApplicationPolicyRunFindingsDto { findings: Pagination; } // Severity sort direction for GET .../runs/:runId findings. `desc` = highest first. export const REVIEW_POLICY_RUN_FINDING_ORDERS = ['asc', 'desc'] as const; export type ReviewPolicyRunFindingOrder = (typeof REVIEW_POLICY_RUN_FINDING_ORDERS)[number]; export const DEFAULT_REVIEW_POLICY_RUN_FINDING_ORDER: ReviewPolicyRunFindingOrder = 'desc'; export const DEFAULT_REVIEW_POLICY_RUN_FINDINGS_LIMIT = 50; export const MAX_REVIEW_POLICY_RUN_FINDINGS_LIMIT = 100; // Sort keys for GET .../runs. Order is alphabetical; default at the API is startedAt desc. export const REVIEW_POLICY_RUN_SORTS = ['applicationName', 'findingsCount', 'startedAt', 'status'] as const; export type ReviewPolicyRunSort = (typeof REVIEW_POLICY_RUN_SORTS)[number]; export const DEFAULT_REVIEW_POLICY_RUN_SORT: ReviewPolicyRunSort = 'startedAt'; export const REVIEW_POLICY_RUN_ORDERS = ['asc', 'desc'] as const; export type ReviewPolicyRunOrder = (typeof REVIEW_POLICY_RUN_ORDERS)[number]; export const DEFAULT_REVIEW_POLICY_RUN_ORDER: ReviewPolicyRunOrder = 'desc'; export const DEFAULT_REVIEW_POLICY_RUNS_LIMIT = 20; export const MAX_REVIEW_POLICY_RUNS_LIMIT = 100; // Offset-paginated runs list. Policy header comes from GET .../:policyId. export type ReviewPolicyRunsDto = Pagination; // Trailing-time windows the summary can be scoped to. Order is semantically // meaningful (shortest to longest) for rendering the selector. export const REVIEW_POLICY_SUMMARY_WINDOWS = ['24h', '7d', '30d'] as const; export type ReviewPolicySummaryWindow = (typeof REVIEW_POLICY_SUMMARY_WINDOWS)[number]; export const DEFAULT_REVIEW_POLICY_SUMMARY_WINDOW: ReviewPolicySummaryWindow = '24h'; export interface ReviewPolicySummaryDto { // `activePolicies` is a point-in-time count and is not affected by `window`. activePolicies: number; totalRuns: number; findings: number; // 0–100. Zero when there are no qualifying runs in the window (no divide-by-zero). passRate: number; window: ReviewPolicySummaryWindow; } export type CreateReviewPolicyBody = | { policyType: 'built_in_security_scan'; mode?: ReviewPolicyMode; scope?: ReviewPolicyScopeInput } | { policyType: 'security_agent'; source: 'superblocks_managed'; mode?: ReviewPolicyMode; scope?: ReviewPolicyScopeInput; } | { policyType: 'security_agent'; mode: ReviewPolicyMode; name: string; prompt: string; scope?: ReviewPolicyScopeInput; }; export type UpdateReviewPolicyBody = { status: AiAgentStatus }; export type UpdateReviewPolicyConfigBody = | { activeVersionId: string; policyType: 'built_in_security_scan'; mode: ReviewPolicyMode; scope?: ReviewPolicyScopeInput; } | { activeVersionId: string; policyType: 'security_agent'; source: 'superblocks_managed'; mode: ReviewPolicyMode; scope?: ReviewPolicyScopeInput; } | { activeVersionId: string; policyType: 'security_agent'; mode: ReviewPolicyMode; name: string; prompt: string; scope?: ReviewPolicyScopeInput; };