// Vocabularies shared by the Phase 2 review screens. Each list mirrors a CHECK constraint in the schema, so a // value the UI offers is a value the column accepts. Drifting these apart produces a form that submits and // then fails at the database, which is the worst place to discover a typo. // document_type, migration 0072. export const DOCUMENT_TYPES = [ { value: 'solicitation', label: 'Solicitation' }, { value: 'amendment', label: 'Amendment' }, { value: 'pws', label: 'Performance work statement' }, { value: 'sow', label: 'Statement of work' }, { value: 'soo', label: 'Statement of objectives' }, { value: 'labor_categories', label: 'Labor categories' }, { value: 'pricing_template', label: 'Pricing template' }, { value: 'evaluation_criteria', label: 'Evaluation criteria' }, { value: 'security', label: 'Security' }, { value: 'q_and_a', label: 'Questions and answers' }, { value: 'past_performance', label: 'Past performance' }, { value: 'subcontract_scope', label: 'Subcontract scope' }, { value: 'customer_scope', label: 'Customer scope' }, { value: 'attachment', label: 'Attachment' }, { value: 'other', label: 'Other' }, ] // scope_type, migration 0076. export const SCOPE_TYPES = [ 'objective', 'task', 'deliverable', 'labor_category', 'staffing_quantity', 'skill', 'certification', 'clearance', 'customer_experience', 'location', 'travel', 'schedule', 'security_control', 'reporting', 'transition', 'key_personnel', 'pricing_instruction', 'evaluation_factor', 'compliance_clause', 'assumption', 'dependency', 'risk', 'other', ] // The staffing relevant subset, matching staffingScopeTypes in internal/modules/opportunities/draftgen.go. // These are the types that generate a requirement draft, and the screen says so rather than leaving a reviewer // to wonder why accepting an evaluation factor produced nothing. export const STAFFING_SCOPE_TYPES = new Set([ 'labor_category', 'staffing_quantity', 'key_personnel', 'skill', 'certification', 'clearance', 'customer_experience', ]) // clearance_level and polygraph, migration 0077. export const CLEARANCE_LEVELS = ['unknown', 'none', 'confidential', 'secret', 'top_secret', 'ts_sci'] export const POLYGRAPHS = ['none', 'ci', 'full_scope'] // MaxDocumentBytes in internal/modules/opportunities. Kept in step with the Go constant deliberately: the // Phase 2 trial found that the REAL limit in production was nginx's 1 MB default, not the application cap, so // the number a user is shown must be the number that is actually enforced end to end. export const MAX_UPLOAD_BYTES = 64 * 1024 * 1024 export function humanBytes(n: number): string { if (n < 1024) return `${n} B` if (n < 1024 * 1024) return `${(n / 1024).toFixed(0)} KB` return `${(n / (1024 * 1024)).toFixed(1)} MB` }