Fix job seeker submission failing: wrong API prefix and missing auth header
All checks were successful
build-and-release / build (push) Successful in 1m46s

job-seeker-custom-data.ts hit /api/gateway/jobseeker/profile/me — a prefix
that never existed in production (see the comment in lib/api.ts, which
every other authenticated call already follows); it 404s against the real
ingress, which routes /api/* straight to the gateway. Its local apiFetch
also never sent an Authorization header, which AuthUser requires (no
cookie fallback), so even the corrected path would 401.

This is why RoleWizard's submit flow broke for JOB_SEEKER specifically:
handleSubmit() calls savePortfolio() first, which calls
updateJobSeekerCustomData() (JOB_SEEKER's portfolioModel is "custom_data"),
which threw on the failed fetch and aborted the whole submission before
the actual profile PATCH or submit-for-verification call ever ran.
Confirmed against production: verifications has 5 rows for COMPANY, 1 for
PHOTOGRAPHER, 0 for JOB_SEEKER ever, despite a job seeker having fully
filled out the wizard (including an uploaded document) days ago.

Same file backs readJobSeekerProfile/updateJobSeekerCustomData used by
PortfolioPage, JobSeekerJobsPage, and JobSeekerSavedJobsPage too — all
four were broken the same way.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Ashwin Kumar Sivakumar 2026-07-30 21:53:06 +05:30
parent 9358ab541f
commit 65bdefadc7

View file

@ -1,5 +1,3 @@
const API = '/api/gateway';
export type JobSeekerProfile = { export type JobSeekerProfile = {
id: string; id: string;
user_id: string; user_id: string;
@ -14,12 +12,26 @@ export type JobSeekerProfile = {
custom_data?: Record<string, unknown> | null; custom_data?: Record<string, unknown> | null;
}; };
// The K8s ingress routes any /api/* path directly to the Rust gateway service —
// there is no /api/gateway indirection in production (see ~/lib/api.ts). Hit
// the path as-is, and send the same Authorization bearer token every other
// authenticated call uses — AuthUser on the backend only reads that header,
// there is no cookie-based fallback.
function getAuthHeaders(): Record<string, string> {
const token = typeof window !== 'undefined'
? (sessionStorage.getItem('nxtgauge_access_token') || '')
: '';
return {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
};
}
async function apiFetch(path: string, opts?: RequestInit) { async function apiFetch(path: string, opts?: RequestInit) {
const cleanPath = path.startsWith('/api/') ? path.slice(4) : path; return fetch(path, {
return fetch(`${API}${cleanPath}`, {
...opts, ...opts,
credentials: 'include', credentials: 'include',
headers: { 'Content-Type': 'application/json', ...(opts?.headers ?? {}) }, headers: { ...getAuthHeaders(), ...(opts?.headers ?? {}) },
}); });
} }