Deploy to S3 / deploy (push) Successful in 36sDetails
Storing a CV without a job no longer rides the cv_upload pipeline, which
created a candidate user account and an inbox row — stored CVs were
leaking into the Candidates screen. New cv-bank endpoints instead write
apply_via=cv_bank rows in manual_upload_candidate (nullable user/job
FKs): file + parsed text only, no account, no inbox entry, no scoring,
and email is optional (captured when the CV contains one). The CV Import
screen now shows the bank itself below the dropzone — browse, download
(existing /documents/download route) and delete.
E2E-verified: uploads land as BANKED rows with user_id NULL, zero new
accounts or inbox rows, UI delete works, Candidates screen unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deploy to S3 / deploy (push) Successful in 37sDetails
Backend: new candidate_forms domain (requisition, interview analysis,
cultural fit) with XOR inbox/manual keys, server-recomputed section
averages and combined summary, INTERVIEW-stage gate (409), history
events, INTERVIEWS_* permissions + 008 RBAC seed; offers table gains
the seven Annexure-J fields.
Frontend: Forms tab in the candidate profile (paper-exact labels from
/forms/definitions, rating tables, score summary tiles, completion
dots); profile converted to a full page at /candidate/:userId opened
from Candidates, Talent Pool and Pipeline; live Advance Stage now calls
PATCH /candidate/stage; workflow-ordered tabs; responsive pass verified
by headless-Edge screenshots at 375-2400px; Stars import crash fix in
Interviews; Matching tab strip wraps on phones.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Builds the four remaining analytics gaps from the architecture plan:
- Report library (REQ-ANL-03): new backend/reports module - saved reports
as parameterisations of the governed analytics queries (never free-form
SQL), rolling window_days filters, recorded runs, CSV export via
Content-Disposition. Reports screen gains the library card with
create/run/export/delete plus a results modal.
- Natural-language analytics (REQ-ANL-05, ADR-0010): POST /analytics/ask
maps a question onto one whitelisted intent, runs the same governed
query the dashboard uses, then narrates the numbers. Ask Analytics card
on the Analytics screen; LLM outages 503 without touching the charts.
- Time-to-hire baseline (REQ-ANL-08): KPIs surface tth_baseline_* from
org setting analytics.tth_baseline ({days,source}); not hardcoded
per OPEN-12. analytics added to org-settings categories. Reports TTH
card shows the delta when set.
- Source spend (REQ-ANL-09 cost side): hiring costs can be tagged with a
source channel; source performance returns tagged spend and
cost-per-application, including spend-only rows for channels with zero
applications (wasted spend must stay visible). Log-cost modal and
Source Performance table on Reports; untagged spend stays
cost-per-hire only.
Verified live: migration autogenerated and applied (saved_reports,
report_runs, hiring_costs.source_channel_id), 50 backend tests, vite
build + smoke/token/theme suites, and a headless-browser drive of both
screens end to end.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Introduced a new `MailboxSyncRun` model to manage mailbox synchronization jobs, allowing for tracking of sync status and results.
- Implemented API endpoints for starting mailbox sync and fetching sync status, enabling asynchronous processing of email synchronization.
- Updated the `Email` service to handle mailbox sync operations, including enqueueing tasks and managing sync results.
- Enhanced frontend components to initiate mailbox sync and display sync status, improving user experience and feedback during the sync process.
- Added necessary query keys and local storage management for tracking sync runs in the UI.
This commit enhances the application's email synchronization capabilities, providing a more robust and user-friendly experience for managing mailbox data.
- Added a new `CandidateHistory` model to maintain an append-only audit log for candidate actions.
- Introduced `HistoryRecorder` functionality to log significant events across various modules, including interviews, feedback, and notes.
- Updated existing methods to include `current_user` for tracking who performed actions.
- Enhanced the `EMAIL_URL` configuration in `docker-compose.yml` to allow for environment variable overrides.
- Updated frontend components to support fetching and displaying candidate history.
This commit improves the application's ability to track changes and actions related to candidates, enhancing accountability and transparency.
- Assignees restricted to recruiter-role users (role id resolved from the
roles table per request, not hardcoded); server 422s any other role on
create and update
- New GET /tasks/assignees/fetch: active recruiter users for the picker,
separate from /users/fetch so assigning never needs rbac_users.view
- Creation gated to system_administrator / hr_administrator / recruiter:
allowed role ids searched from the DB and compared to the callers
role_id, on top of the tasks.create permission tag
- manual/005_tasks_rbac_restrict.sql: permission DB follows suit -
hiring_manager / department_head / ceo swap tasks_management for a
view-only tasks_viewer bundle (idempotent, auto-applies at boot)
- UI: assignee dropdown lists recruiters from the new endpoint with
required-field validation; recruiters get an assign-to-me default; the
New Task button honours the creator roles
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- New backend/tasks/ package (offer/ house style): tasks table
(title/status/priority/due_date/assignee_id -> users.id, optional
inbox_id/job_post_id links, soft delete), routes /tasks/fetch|create|
update|delete guarded by new tasks.* permission tags
- Assignees validated against users+roles: must exist, not deleted, not
candidate-role; omitted assignee defaults to the caller; responses carry
assignee_name/assignee_role from one batched join
- TASKS permission module (104 -> 112 tags); manual/004_tasks_rbac.sql
seeds the tags + tasks_management bundle onto 6 staff roles (auto-applies
at startup)
- Tasks.jsx cut over from seed to live: real create/complete/reopen with
optimistic flip, two-click delete in the detail modal, assignee picker
listing real users with roles; live sidebar badge (open-task total);
route now requires tasks.view
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>