- Deleted the `.env.example` file as it is no longer needed; all configurations are now centralized in `backend/.env`.
- Updated `docker-compose.yml` and `docker-compose.dev.yml` to reflect changes in environment variable handling, ensuring that the application reads from `backend/.env` exclusively.
- Adjusted the nginx configuration to improve API request handling and ensure proper proxying for frontend interactions.
These changes streamline the environment setup process and enhance the overall configuration management for local and production deployments.
- Adjusted `VITE_API_BASE` in Dockerfile and docker-compose.yml to allow same-origin requests, enhancing compatibility with nginx proxy settings.
- Increased the `top` query limit in `app.py` to 500 to accommodate frontend requirements while ensuring consistency across job fetching in `Jobs.jsx` and `Managers.jsx`.
- Updated nginx configuration to properly proxy API requests, preventing incorrect responses for job-related endpoints.
These changes streamline the interaction between the frontend and backend, ensuring a smoother user experience when fetching job data.
- 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.
- Updated the interview model to include `graph_event_id` and `web_link` for calendar integration.
- Added methods for setting calendar events and retrieving job titles associated with interviews.
- Modified serializers to include new fields in the interview response.
- Enhanced the job post model to include applicant counts.
- Updated frontend components to handle new fields and improve user experience with calendar event management.
- Introduced image upload functionality in job forms with validation for file types and sizes.
- Improved dashboard and calendar UI for better data presentation.
This commit streamlines interview scheduling and job management processes, enhancing overall application functionality.
Deploy to S3 / deploy (push) Successful in 33sDetails
- New POST /job/assist-field (job_board.create OR jobs.edit): per-field
AI fix/suggest via backend/job_assist package on the shared llm_call.
Suggest is gated on title + experience anchors; decisive typo repair;
provider failures return a generic 503.
- AiFieldAssist component: sparkle button per field with fix/suggest,
loading, preview-before-apply, abort on close; wired into JobForm and
EditJobForm with per-field suggest hints.
- Create Job no longer requires a Buffer channel: without channel_id or
platform the backend saves an internal-only requisition (platform
internal) and never calls Buffer; publishing stays on the Job Board.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 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>
- inbox_messages.ats_score/ats_band written on every completed inbox score;
inbox.ats_id always points at the current ats_results row
- ats_results now holds the supersede-chained history for BOTH inbox and
upload scores (new candidate_id link, inbox_id nullable for uploads)
- migrations/manual/*.sql apply automatically at startup, tracked once per
database in manual_migrations - developers just pull and boot
- 002_backfill_inbox_ats.sql backfills pre-existing scores
- Add Candidate modal: Matching-style role picker above the CV dropzone,
and the CV is scored via /candidate/score after creation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Conflict resolutions:
- backend/job/app.py: dropped duplicate pydantic import (already present below)
- backend/job/candidate/views.py: union of both sides — kept Talha's
_recommendation/_scores_by_message helpers alongside main's manual-upload
create_candidate, merged import lists and module-level config
- frontend/src/lib/apiClient.js: both sides made the same FormData fix;
kept main's version that reuses the shared multipart const
- frontend/src/screens/Candidates.jsx: kept Talha's live-data screen and
ported main's AddCandidate modal onto it — server POST via
candidatesApi.createManual with live job posts, seed-shaped buildRow
replaced by a candidates query invalidation; seed-only BulkAssign dropped
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The decoded attachment is already the CV and the job post is already the JD, so
scoring now fires from the data we have:
- After the agent matches an inbox message, score_message_against_job runs
inline in the match task - against the assigned job if one is set, else the
top suggested job. Failures log and never fail the match.
- When a recruiter assigns a job post, the new inbox.score_message task is
queued in the background so the request never waits on OpenAI.
Idempotent by (message, job): an already-completed score is never paid for
twice. Rows are attributed to the job post owner since background tasks have
no request user. CV Import and the profile Score-with-ATS button remain as
manual fallbacks.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Main stubbed ai_score/recommendation as None in the candidate-profile payload;
fill them from the scoring engine's candidates table, joined by inbox message
(one batched query for the list, assigned-job-preferred for the detail). The
detail payload also gains matched/missing keywords, the critique, and which job
the score was against.
Frontend: TalentPool cards and the profile hero prefer the real score over the
seed placeholder, and the profile grows a Score-with-ATS button (shown when the
candidate has an assigned job and an inbox message) that runs the existing
score_inbox pipeline and repaints via the detail refetch.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>