import { useEffect, useState } from 'react' import { Link, useParams } from 'react-router-dom' import { Building2, Check, Clock, Loader2, MapPin, Paperclip, ShieldCheck } from 'lucide-react' // THE PUBLIC CAREERS PAGES. // // These are the only screens in this product a stranger sees, and the only unauthenticated ones that touch a // tenant's data. Everything about them is deliberately different from the rest of the application. // // NO SESSION, NO SHELL, NO SHARED CLIENT. They are mounted OUTSIDE the authentication gate, beside the invite // acceptance page which has the same property. They do not use lib/api, because that client mints a CSRF // token and sends credentials, and a visitor with no session has neither: it would fire a pointless request // at an authentication endpoint on every page load. They call fetch directly, with credentials omitted, so // the request carries nothing at all. // // THEY ARE LIGHT ON THEIR OWN AND HEAVY ON HONESTY. A candidate is handing over their name, their history and // often their clearance status. The consent they give is explicit, is recorded with what they agreed to, and // is written in the sentence they actually read rather than referenced from somewhere else. // publicGet and publicPost are the whole client. Credentials are omitted rather than defaulted, so no cookie // is sent even if the visitor happens to be signed in to the recruiter application in another tab. async function publicGet(path: string): Promise { const res = await fetch(`/api${path}`, { credentials: 'omit' }) if (!res.ok) { throw new Error(await publicError(res)) } return (await res.json()) as T } async function publicError(res: Response): Promise { try { const body = (await res.json()) as { error?: string } if (body.error) return body.error } catch { // A non JSON body from a proxy or a gateway is not worth parsing twice. } // ONE MESSAGE FOR EVERY REASON A LINK MIGHT NOT WORK, matching what the server does. A page that said // "this posting was closed" would confirm the posting existed, and a page that said "no such employer" // would let somebody walk the list of organizations. Not found is not found. if (res.status === 404) return 'This link is not available. It may have been closed or it may have expired.' if (res.status === 429) return 'Too many requests from here. Wait a minute and try again.' return 'Something went wrong at our end. Please try again shortly.' } interface PublicPosting { token: string title: string summary?: string responsibilities?: string qualifications?: string location?: string remote_allowed: boolean employment_type?: string clearance?: string pay_range?: string published_at?: string closes_at?: string employer: string } // Frame is the whole visual chrome for these pages: a name, the content, and a footer. There is no // navigation, because there is nowhere else for a visitor to go, and offering a menu into an application they // cannot sign in to would be an invitation to a login screen they have no account for. function Frame({ employer, children }: { employer?: string; children: React.ReactNode }) { return (
{employer || 'Careers'}
{children}
Applications are handled by the employer named above. Any clearance you state is recorded as self reported and is never treated as verified. The real check is the hiring client facility security officer through DISS at onboarding.
) } function Loading() { return (
) } function Failed({ message }: { message: string }) { return (

{message}

If somebody sent you this link, ask them for a current one.

) } export function PublicCareersList() { const { slug = '' } = useParams() const [data, setData] = useState<{ employer: string; postings: PublicPosting[] } | null>(null) const [err, setErr] = useState('') useEffect(() => { let live = true publicGet<{ employer: string; postings: PublicPosting[] }>(`/careers/${encodeURIComponent(slug)}`) .then((d) => live && setData(d)) .catch((e: Error) => live && setErr(e.message)) return () => { live = false } }, [slug]) if (err) { return ( ) } if (!data) { return ( ) } return (

Open roles

{data.postings.length === 0 ? (

There is nothing open right now. It is worth checking again in a week.

) : (
    {data.postings.map((p) => (
  • {p.title}
    {p.location && ( {p.location} )} {p.remote_allowed && remote allowed} {p.clearance && ( {p.clearance} )} {p.employment_type && {p.employment_type.replace(/_/g, ' ')}}
  • ))}
)} ) } export function PublicPostingPage() { const { slug = '', token = '' } = useParams() const [p, setP] = useState(null) const [err, setErr] = useState('') useEffect(() => { let live = true publicGet(`/careers/${encodeURIComponent(slug)}/postings/${encodeURIComponent(token)}`) .then((d) => live && setP(d)) .catch((e: Error) => live && setErr(e.message)) return () => { live = false } }, [slug, token]) if (err) { return ( ) } if (!p) { return ( ) } return (

{p.title}

{p.location && ( {p.location} )} {p.remote_allowed && remote allowed} {p.clearance && ( {p.clearance} )} {p.pay_range && {p.pay_range}} {p.closes_at && ( closes {new Date(p.closes_at).toLocaleDateString()} )}
{p.summary && } {p.responsibilities && } {p.qualifications && } ) } function Prose({ title, body }: { title: string; body: string }) { return (
{title &&

{title}

}

{body}

) } const CLEARANCE_CHOICES = [ '', 'None', 'Public Trust', 'Secret', 'Top Secret', 'TS/SCI', 'TS/SCI with polygraph', ] // The exact sentence somebody agrees to. It is stored with the application, so it has to be the words that // were on the screen rather than a version number pointing at a policy that can change afterwards. const CONSENT_TEXT = 'I agree that the employer may store the details I have provided, including any resume I attach, and may ' + 'contact me about this role and other roles they think I would suit. I understand that any clearance I ' + 'state here is self reported and is not treated as verified.' function ApplyForm({ slug, token }: { slug: string; token: string }) { const [full_name, setName] = useState('') const [email, setEmail] = useState('') const [phone, setPhone] = useState('') const [location, setLocation] = useState('') const [clearance, setClearance] = useState('') const [cover_note, setNote] = useState('') const [file, setFile] = useState(null) const [consented, setConsented] = useState(false) const [sending, setSending] = useState(false) const [sent, setSent] = useState(false) const [err, setErr] = useState('') if (sent) { return (

Your application is in.

A recruiter reads every application. If it is a fit you will hear from them directly, and there is nothing further you need to do.

) } const submit = async (e: React.FormEvent) => { e.preventDefault() setErr('') if (!consented) { setErr('Please agree to the statement above before applying.') return } setSending(true) try { // Multipart, because a resume rides along with the fields. The consent text is sent with the // submission rather than assumed by the server, so what was agreed to is what gets stored. const form = new FormData() form.append('full_name', full_name) form.append('email', email) form.append('phone', phone) form.append('location', location) form.append('clearance', clearance) form.append('cover_note', cover_note) form.append('consent_text', CONSENT_TEXT) form.append('consented', 'true') form.append('source', 'careers_page') if (file) form.append('resume', file) const res = await fetch( `/api/careers/${encodeURIComponent(slug)}/postings/${encodeURIComponent(token)}/apply`, { method: 'POST', credentials: 'omit', body: form }, ) if (!res.ok) { throw new Error(await publicError(res)) } setSent(true) } catch (e) { setErr((e as Error).message) } finally { setSending(false) } } const field = 'w-full rounded-md border border-line/70 bg-navy-950/60 px-3 py-2 text-sm text-ink outline-none placeholder:text-faint focus:border-blue/60' const label = 'block text-[11px] font-bold uppercase tracking-wider text-muted' return (

Apply

void submit(e)}>