Release notes
The Recruitment Agency Operating System — Streamlined operations, better submissions.
A flaw in how the system identifies the tenant from an incoming request meant that certain server-level IP addresses were being mistaken for tenant names, causing candidate creation and résumé upload to fail with a support-contact error for real users. The system now correctly ignores IP addresses when determining the tenant, and the error no longer occurs.
Every time a requirement was published or deactivated, the corresponding update to EzRefer was silently failing and retrying every 30 minutes without ever succeeding. The root cause was that the wrong identifier was being used to locate the job on EzRefer's side. The correct identifier is now used, and a job that cannot be found is automatically re-created rather than retried forever.
The Global Search link has been restored to the sidebar navigation for every tenant. Tenants that have not yet been opted in to the feature will see a 'Feature Unavailable' page if they click it — this is intentional, allowing tenants to be enabled one by one by an administrator.
A candidate's salary sitting exactly on the floor of the lowest configured pay band was silently skipped, resulting in no billing charge being applied. The lowest pay band is now always treated as inclusive of its lower boundary, ensuring every placement is billed at the correct rate.
A misconfigured environment value caused every request to the recent-searches and job-description parsing features to fail silently with a not-found error. The service now applies a safe default when that value is blank or missing, restoring normal operation.
A conflict between two database upgrade scripts sharing the same version number was preventing any new deployment from completing. The affected scripts have been renumbered to eliminate the clash, restoring the ability to deploy. No data already in production was affected.
Users who lacked permission to view billing rate cards were previously triggering a server error, which raised a system alarm. The billing rates section is now hidden entirely for those users upfront, and the underlying error is handled gracefully rather than causing a crash. Access controls on the server side are unchanged.
KPI summary cards on the ROI screen now round values to two decimal places, and figures shown in the detailed ROI tables are exact whole numbers where appropriate. This corrects misleading or inconsistently formatted numbers that users would have seen previously.
A clash between two database migrations assigned the same version number was causing a risk of failed or inconsistent upgrades across all 16 UAT tenants. The conflict has been resolved by removing the redundant migration that had never actually been applied, leaving all tenants in a consistent and correct state.
Two related bugs on the requirement edit screen have been resolved. The Client SPOC field was always blank when opening an existing requirement because the selected contact was being dropped before the data reached the screen — it now appears correctly. Separately, the Org SPOC confirmation prompt was firing on every save even when the same person was re-selected; this was caused by a mismatch in how the employee identifier was formatted, and the comparison now works consistently.
When Global Search returned zero candidates with no visible error, there was no way to determine which stage of the process had failed. Logging has been added at each step of the search pipeline so the cause can be identified quickly. Additionally, a failure in one search source no longer causes all other sources to return nothing — each source now succeeds or fails independently. Separately, connection errors to the AI gateway now record the specific underlying cause rather than a generic message.
A type-annotation incompatibility was causing cost data processing to fail on the server's runtime version. This has been resolved, so cost reporting now executes without errors.
The Create and Workflow options under Candidate Management were silently disappearing when administrators opened the permission group configuration screen, making it impossible to assign those rights. The underlying access-rights data was always correct — only the display was affected — and this is now resolved. Permission enforcement was unaffected throughout.
A new toggle in the Hiring Details section of each requirement lets recruiters choose whether to publish that role to EzRefer. A status badge shows whether the listing is pending, synced, failed, or deactivated, giving recruiters immediate visibility into the sync state. Publishing and deactivating happen automatically in the background, so saving a requirement is never slowed down by the connection to EzRefer.
When a candidate's CTC fell exactly on the boundary between two billing slabs, it was incorrectly charged at the higher slab's rate. This has been corrected so that boundary values are always assigned to the lower slab, matching the intended billing rules.
Super-admins can now enable or disable the EzRefer publishing option on a tenant-by-tenant basis from the admin panel. Tenants that have not been opted in will no longer see the toggle at all on their requirement forms, and any attempt to publish to EzRefer for those tenants is blocked server-side regardless of form state. A background job also automatically retries any publish attempts that previously failed due to transient errors, so stuck requirements no longer need manual intervention to recover.
A safeguard was added to detect and stop circular chains in reporting structures before they could cause the application to become unresponsive. Organisational hierarchies with accidental loops are now handled gracefully.
Every attempt to publish or update a job from EzRecruit to EzRefer had been rejected since the sync feature was deployed, because a date field was being sent in the wrong format. Both the root cause and a follow-up correction to the initial fix have now been applied, and date values are transmitted correctly. Job sync should now complete successfully on the next retry cycle.
Every job publish and update sent to EzRefer was being transmitted in the wrong format, causing all sync requests to be rejected. The root cause has been identified and corrected, so new and updated job postings now flow through reliably.
When a new tenant is set up, the global search capability is switched off unless explicitly enabled. This gives administrators deliberate control over which tenants have access to the feature rather than having it active automatically.
A copy-paste leftover caused the bulk CV upload endpoint to be registered twice in the API, producing a duplicate entry in the API's auto-generated documentation and potentially confusing any tools or integrations that consume it. The redundant registration has been removed; the endpoint itself is unchanged and continues to work as before.
When EzRecruit classifies a candidate's role or company into an industry, that result is now stored in a shared database cache rather than discarded on each restart or across parallel servers. This reduces repeated AI calls for the same lookups, lowering cost and speeding up CV processing at scale.
The full test suite (219 tests) was previously never executed automatically, meaning code issues could reach a release undetected. Every build now runs all tests and will block a release if any fail.
The CV batch-upload endpoint was registered twice in the API, causing it to appear duplicated in the API catalogue used by integrations and tooling. The redundant copy has been removed; the endpoint itself is unchanged and continues to work as before.
The AI call-log service previously could not run its automated tests without a fully configured live environment, meaning tests were silently skipped in the build pipeline. This has been corrected so all 219 tests now pass in the pipeline, and a passing test run is required before any new version is published.
When the CV parser determines a candidate's industry or domain, that result is now stored in a shared cache accessible to every running instance. Previously each instance worked independently, so the same classification could be performed many times over, adding cost and latency. Repeated lookups for the same company and role now return instantly from the cache.
Four email notification types — application user OTP, admin login OTP, admin password reset, and admin forgot-password — were silently falling back to a secondary email provider on every send due to a missing subject field required by the primary provider. Emails always reached recipients, but the repeated fallback was firing monitoring alerts. The subject is now set correctly so all four types route through the intended provider without errors.
Previously, users who lacked permission to view ROI analytics were shown the page anyway, with every data table failing and multiple error notifications appearing. They now see a single, clear access-denied screen instead. This eliminates confusion and removes the misleading impression that something is broken.
Expanding a row in the ROI drill-down no longer freezes the tab. A stray summary row that was incorrectly appearing in the employee-filtered view has also been removed.
Both the paste-text and file-upload paths for job description parsing were being rejected before any processing occurred, meaning no JD submitted through the normal UI was ever parsed. The routing layer now correctly handles both input types and directs each to the appropriate downstream endpoint.
Streamed responses containing em-dashes, accented letters, or emoji were being corrupted before reaching the user and being stored in chat history. The encoding mismatch has been corrected, so all characters now display and save correctly.
When ranking a batch of candidates, up to 4 out of 15 could come back with no score, strengths, or gaps shown — silently discarded with no error. The root cause was the AI model occasionally shortening a candidate's identifier, causing the score lookup to miss. Candidates are now labelled with simple positional references during ranking so the model never needs to reproduce a long identifier, and any remaining mismatches are logged as warnings rather than dropped.
The override permission used to bypass a blocked automated review has been aligned across two additional repositories, matching the safeguard already standard elsewhere in the organisation.
An automated dependency update introduced a version of a machine-learning library that is incompatible with the Python version this service runs on, causing every UAT build to fail for roughly 24 hours and preventing any changes from reaching the UAT environment. The dependency has been pinned back to the last known-good version, restoring the pipeline. Upgrading to a newer version will be done deliberately as a separate piece of work.
Eight service credentials, including database, search, and AI API keys, have been moved out of build artefacts into runtime-injected secret storage, extending a protection standard already applied elsewhere in the platform. Four additional credentials were moved to properly secured storage in the deployment pipeline, verified to match previous values before going live.
In live UAT traffic, the AI model occasionally returned a candidate identifier with extra text run into it, which the ranking logic did not recognise, causing that candidate to be left unscored. The fix detects this specific malformed pattern and recovers the correct identifier. Previously the failure was silent; it only came to light because earlier logging improvements made unranked candidates visible.
The Global Search screen was designed to show step-by-step progress as a search runs, but the backend was returning a single blocked response only after all work was complete, causing the server to reject the streaming request entirely with an error. The endpoint now streams results progressively to the frontend as they arrive, matching the intended user experience.
A baseline of expected search results has been generated from 58 real recorded conversations, enabling the team to run future configuration changes against it and detect any drift in candidate results. This unblocks a pending decision about a caching feature that could not be evaluated without a reference baseline.
The image-handling framework used across the application has been updated to the latest patched version, addressing a publicly disclosed vulnerability. Separately, service credentials embedded in container images have been moved to runtime-only injection, and a previously incomplete credential rotation has now been completed.
Recruiters can now page through all matching candidates beyond the first 20 results, with a clear count of total matches shown. If a network drop interrupts an in-progress search, a Reconnect button lets the session resume from where it left off rather than losing the results entirely. Error messages throughout the search experience have been rewritten in plain language instead of displaying raw technical codes.
Users navigating to the received-goals settings page when they had no goals assigned were triggering a recurring server-side crash that had been occurring every few minutes since June. The page now loads correctly in all cases.
Five database tables used to track AI call attribution and per-tenant AI balance and quota were missing from the standard tenant setup process, meaning UAT had none of them and production was missing the balance tables entirely. Calls continued to work but attribution rows and balance lookups were silently failing on every call. These tables are now part of the standard tenant provisioning flow, closing the gap between environments and ensuring cost and usage data is captured correctly going forward.
The application has been prepared to send emails via a second provider at a significantly lower cost (approximately $0.10 per 1,000 emails versus a $35 flat monthly fee). The existing email provider remains active; no sending behaviour changes until the switch is explicitly enabled.
After every deployment, users who had the application open in a tab would receive an error on any action — submitting a form, saving a record — until they manually refreshed the page. This was caused by a security key being regenerated on every build, making the newly deployed server unable to recognise requests from pages loaded before the deployment. The key is now fixed and stable across all future builds, so this class of disruption will not recur.
One tenant was missing four database tables required for AI balance and quota tracking, and all tenants were missing a user identifier column on AI usage records. Both gaps are now corrected in production. The changes are safe to apply repeatedly and have no effect on tenants whose schemas were already up to date.
Previously, switching email infrastructure required moving all notification types at once. A new configuration option now allows individual notification types — welcome emails, OTP codes, interview invites, and so on — to be moved to the new provider independently, while everything else continues on the current provider. This enables a controlled, low-risk rollout with the ability to pause or reverse at any step.
The automated pull-request review tool can now detect when a finding it raises was also raised in an earlier review of the same change. Repeated findings are labelled as such and counted separately, making it easier for reviewers to see which problems have persisted across revisions rather than treating every round as a fresh list.
A July code change accidentally removed the database session that these scheduled jobs depend on, causing every single run to fail silently — 219 consecutive failures across all production tenants, with zero post-interview messages delivered in two weeks. The jobs now open a proper transaction per interview, load all required data in one query, and skip a single failing record instead of halting the entire tenant's queue. A data clean-up also marks the backlog of past interviews that can no longer be reminded as resolved, so they stop appearing as outstanding work.
Candidates applying for jobs through the public portal were receiving a one-time password email intended for admin users, complete with admin portal branding and a greeting placeholder that was never filled in. The verification email for external candidates now uses its own dedicated template with the correct audience and content.
Goal creation and edit notification emails were silently broken when the email provider requires an explicit subject line. This was caught during pre-launch testing of the new email provider and fixed before it could affect live traffic.
A recent deployment shipped without the expected credentials baked into the image, causing all resume uploads to fail for approximately 30 minutes. The service now falls back gracefully to the server's attached identity when explicit credentials are absent, so a missing build secret no longer takes the upload feature offline.
Every deployment of the admin portal was generating a new random encryption key, which invalidated any in-flight server actions from the previous version. The key is now stable across deploys, preventing unexpected failures for users active at the moment of a release.
Three in ten candidate self-bookings were failing silently due to a race condition when generating offer IDs, and every attempt to decline an interview returned an authentication error. Both are now fixed. Additionally, raw database error messages that were previously shown verbatim to candidates on booking failure have been replaced with plain, readable text. The 'Not Interested' and 'Request other times' buttons are now also visible even when no slots remain.
Candidates were receiving a WhatsApp confirmation for bookings that subsequently failed, and a failed message send could roll back an otherwise successful booking. The confirmation now only fires once the booking is fully committed. Separately, the interview time shown in the message was displaying 5.5 hours off due to a timezone handling error; it now shows the correct local time.
The platform can now send notifications through either the existing email provider or a new alternative, controlled by configuration with no code change required. If the new provider fails on a given send, the system automatically retries through the original provider and raises an alert, so no notification is silently lost. Three additional notification types have also been prepared for use with the new provider when needed.
All database-backed search routes were returning errors on UAT because the database connection was being made without the encryption the server requires. Encrypted connections are now enforced, restoring search functionality. Internal database calls within the search pipeline were also aligned with the service's asynchronous design to ensure consistent, predictable behaviour.
Re-running a rollback to the currently deployed image previously failed partway through, causing the forced redeploy step to be skipped. The process now recognises that the image tag is already correct and proceeds to trigger the redeploy as intended.
Two crashes in the reporting endpoints, a conversion ratio correct only by accident, a permanent guard against the startup crash recurring, three fields the interface expected but never received, and code linting re-enabled after having been switched off.
Ten of twenty-three client databases were stranded up to 140 versions behind. Reactivating any one of them would have run the entire backlog against live traffic.
A limit in how cloud services are listed meant that four of the twenty-three services — including the main production backend — were invisible to the rollback process. Had a rollback been triggered during an incident, it would have failed silently at exactly the wrong moment. All services are now found correctly regardless of how many exist.
The full internal API reference, covering 582 routes with parameters and data schemas, is no longer served on production. Development and staging environments retain access for internal teams, tightening the boundary between public and internal surfaces.
The web framework used by the AI routing service was updated to address a known session-handling security advisory. A YAML parsing vulnerability in the admin portal's linting configuration was also resolved. Both updates eliminate publicly disclosed security risks.
Database passwords and third-party API keys used in build pipelines have been moved to encrypted secret storage, matching the protection standard used elsewhere in the platform. Automated deployment to the UAT environment is also restored.
AI calls served from cache were being billed correctly but logged as if no caching occurred, making it impossible to measure whether caching was working or saving money. Both paths that write billing records now capture the actual cache token counts, so reports and future decisions about caching strategy will reflect reality.
JD parsing was locked to one setting at ₹0.66 per call with no way to tune it, plus a quality guardrail added on ranking.
Users with an expired session saw a raw system code instead of the login page; admin portal tenant links rendered as broken URLs; and Goal Settings demanded create-level permission on a read-only screen.
A candidate's technology field grew each time they were tagged to a requirement, with no cap, eventually overflowing and crashing evaluation submit.
Each silently lost or double-counted revenue rather than producing an error, which is why none had ever been reported. Also fixed: US-region résumé file paths were being corrupted.
Automation had produced eleven unreviewed automatic production releases in a single day. An explicit approval is now required, and direct pushes to production are blocked — everything must pass through UAT first.
Previously a failure left no trace whatsoever and retried silently forever. The single biggest visibility gain of the period — and what surfaced the two items below.
Monthly budget per client with per-person and per-feature allowances, a Super Admin panel to set them live without a release, a client-facing usage dashboard, and every AI call attributed to the employee who triggered it.
Custom tracker and full redesign — the largest single product change of the period.
Seven filters were shown in the interface but ignored by the system. Those now work, along with column sorting and Recruiter Name in both the grid and the Excel export.
Resolved, and the underlying database update process re-enabled after having been switched off since early August. Three client workspaces that could not receive any further updates were unblocked at the same time.
A duplicate component name crashed the application at startup, so every release was automatically rolling back and no new code could reach production.
A database query was reading a field it never requested. Masked until now by the startup crash above.
Editing older requirements crashed outright, and long skill lists were rejected on save.
Any client without location data saw an error rather than an empty list, affecting nine separate modules.
Two production tables were missing entirely, JD parsing and search-query generation were reported as a single cost line hiding each one's real cost, and queries were hardened against schema drift.
Eighteen internal section labels — "Fintech", for example — were being extracted as real company names on every CV.
Users hitting an AI Search limit saw nothing because the message went to a component that no longer existed; Global Search was hidden from the menu while still in build; and a health check was reporting a false alarm on a healthy service.
Credentials across six services moved into masked storage. Previously every collaborator could read them.
Deep health checks, encrypted-connection verification, pinned dependencies and two production alarms. The service previously had none.
Signing in now evicts the previous device, so one account cannot be shared across people simultaneously.
A supervisor can now have several active collaborators attached at once, selected together rather than one at a time.
Batch upload and parsing of résumés, rather than one file at a time.
Filtering, sorting and paging now happen on the server, so the roster stays fast as record counts grow.
A single malformed Word document could permanently hang the conversion service, taking down CV parsing for everyone on that instance. Now isolated per document, with the monitoring alarm repaired and extended.
Image zoom, a logo link back to the dashboard, a status picker, validation feedback on tags, and current-designation autocomplete.
The analytics module and its ROI enhancement, including the menu and permission wiring to reach it.
The menu entry, permissions, and proxy layer for Global Search, laying the groundwork for the feature that later shipped.
Path traversal, credentials being written to logs, an injection route into the parsing function, and personal data appearing in log output — all fixed together.
Supporting-document input handling, designation autocomplete with exact matches ranked first, and module URL segregation behind a proxy layer.
Nothing matches those filters.
Release notes
Bridging talent, building futures — verified student data, honest match scores.
From the Recommended Candidates page, a recruiter can now open a candidate's full Career Passport — covering academic background, skills, location, and willingness to relocate — without the candidate having applied yet. Contact details, social links, and portfolio URLs remain hidden until the candidate applies or accepts an invitation, preserving the pre-application privacy boundary.
The old placement-report tab has been replaced with a full Report Center. Universities can now export statutory returns in the formats required by national accreditation bodies, build and save custom report templates, and view a College Reports analytics page.
The registration wizard has a new two-pane layout matching the login page, with floating-label inputs and a persistent step card. Email verification is now passive — the page polls for confirmation automatically rather than asking the candidate to paste a token. The Early Bird fee has been reduced, and the discounted price is only shown when a real discount applies. Retrying payment after a network hiccup no longer produces an error.
Previously, uploaded files were written to the container's local disk and lost every time a new version was deployed. Files are now stored in cloud object storage and survive deployments. Data-erasure requests correctly delete the stored object, not just the database record.
Three code-quality errors introduced over recent days were preventing the automated deployment pipeline from shipping frontend changes. All three are resolved and the pipeline is running normally again.
Links to the Privacy Policy and Terms and Conditions in the student, company, and CV Analyzer footers were pointing to a non-existent anchor and silently redirecting users back to their dashboard. Both pages now exist and all six links point to them correctly.
The infrastructure definition had drifted from the actual running environment in ways that would have caused an outage if applied — including disabling the database deletion guard and removing critical credentials. The definition now accurately reflects production, so routine infrastructure changes can be applied safely.
Five QA-reported issues are fixed: document uploads now show a re-upload option when a preview is unavailable and surface the real error message on failure; uploaded documents in pending review no longer appear as missing in the count and badge; the Proof of Work section's edit buttons now open the editor; outline-style buttons that were invisible against the page background are now legible; and profile photo uploads no longer fail with an unrecognised-purpose error. Additionally, the identity/name edit pencil now appears on hover like every other section rather than requiring a separate toggle.
In the Job Preferences drawer, typing a space after the first word in the Roles, Locations, or Industries fields caused the space to be erased immediately, making it impossible to enter multi-word values. The fields now accept spaces freely and only process the input when the user moves away.
A sweep across the student, university, company, and admin portals removed hardcoded fixture values that were being shown as real data — including a student's identity fields and profile photo, default academic scores saved when fields were left blank, a fixed requirements list shown to companies with no real postings, and an all-zero KPI dashboard that appeared on real fetch failures. A defunct generator of 216 fabricated student records was also deleted.
A data-column mismatch meant the CGPA component of job-match scores and placement-drive eligibility checks was silently reading a legacy field that nothing writes to, effectively ignoring CGPA entirely and excluding real students from drives that set a minimum CGPA. Both now read the correct column.
The invitation email sent to students now contains a real activation link. Following that link shows the student whose invitation it is, collects a password, and completes account creation — the full flow from invite to first login now works end to end.
When a student profile or job requirement contained no title, skills, or other descriptive text, the matching service attempted a network call that always failed with an error. The service now detects empty input immediately and falls back gracefully, with no error logged and no wasted call.
A new Students section in the university portal lists every student on the roster — name, enrolment number, email, phone, and CGPA — with each entry linking to a read-only profile page. Phone numbers and CGPA values now come from the correct data columns, fixing a gap where both fields were blank or stale for real students.
Universities that have not configured their own course list now show the platform's standard course options instead of a blank dropdown. A student's first-ever document upload (CV, marksheet, ID, etc.) now saves correctly and appears in their profile. The verification status indicator now names the specific field awaiting review rather than showing a generic badge.
Job postings and recruitment drives that do not specify certain criteria (such as required skills, grade threshold, or graduation year) no longer award artificial full credit for those unset dimensions. Scores now only measure the criteria a posting actually states, giving recruiters an honest ranking rather than an inflated or fabricated one.
The admin view of a drive's shortlisted and offered counts now reflects live figures instead of frozen values from the time the drive was created. Application records also now carry a distinct company description rather than repeating the company name.
When a student's document is approved or rejected, the in-app notification bell now shows which field was reviewed and, for rejections, the reviewer's stated reason — matching the detail that was already present in the email. Greyed-out contact controls also now display their reason as visible text rather than a hidden tooltip.
When creating a new job requirement, all fields now start completely blank instead of pre-filled with fabricated sample content. Similarly, the navigation bar no longer briefly displays a made-up person's name and company during page load or when a session cannot be found — it now shows a genuinely empty state until real account details are available.
Students now receive a daily email summarising their pending job matches. Two scoring bugs were also resolved: closed roles were previously matched and notified to students as if they were still active, and match scores were incorrectly clamping to 100% for most real jobs, making ranking unreliable. Both are now fixed, so the matches students see are accurate and meaningfully ranked.
A platform-wide gap meant that any job posting with a backlog limit was invisible to every student — the backlog field had never been connected to the eligibility system. Separately, CGPA and graduation year were also not being read correctly from student profiles, so those filters silently excluded candidates who should have qualified. Both gaps are now resolved, and students can enter their active backlog count directly in their profile. A database correction was applied to existing records, and three students who were previously excluded from a real posting now correctly appear as eligible.
In two places — the Career Passport document vault and the CV Analyser — a file that had gone missing after a server restart would display raw technical error text where a document preview should appear. Both now show the same clear, actionable message already used elsewhere in the product, prompting the student to re-upload the file.
A timing issue meant that clicking Edit on a requirement and then saving could create a brand-new duplicate posting instead of updating the original. The save now completes before navigation proceeds, so the correct posting is always updated.
Three profile fields — gender, current location, and willingness to relocate — were collected from candidates but never fed into the matching engine's ranking calculation, so they had no effect on job fit scores. A separate bug was also silently overwriting the relocation preference with a stale default value on every profile save. Both issues are resolved; match scoring now reflects what candidates actually entered.
Several pages were silently displaying hardcoded or stale information: the university topbar showed a fixed sample institution name rather than the real university's identity, the admin settings page could overwrite live settings with defaults on a failed load, placement cell pages pulled the wrong name from an outdated source, and a managed hiring detail page briefly showed a false 'not found' for real engagements. All five issues are resolved — every portal page now reflects accurate, live data.
Job postings can carry a minimum percentage eligibility threshold, but students had no way to record a percentage-scale score — only a CGPA. This meant any job using that threshold effectively excluded every student. Students can now specify whether their academic score is a CGPA or a percentage, and the correct value is used when matching them against job eligibility criteria.
A batch of issues reported through QA has been addressed across the platform: student profile editing, CV Analyzer behaviour, document verification coverage, university admin invitations (which previously had no working endpoint), dashboard notices, and drive registration closing-date enforcement. Closing dates entered during drive setup are now correctly saved and enforced rather than silently discarded.
Uploading resumes, videos, logos, or offer letters above 1 MB was causing a silent crash immediately after the earlier update went live. The upload size limit has been raised to 55 MB, restoring reliable file submission across all upload points in the platform.
When a candidate tries to upload a self-introduction video larger than 50 MB, they now see an actionable error straight away, before any upload begins. This prevents wasted time waiting for a failed upload and makes the file-size limit explicit.
Candidate profiles were showing garbled skill data instead of readable skill names; this is now resolved. Separately, the summary counts shown on the Companies and Universities list screens were frozen at the time each record was created — they now reflect real-time figures for requirements, hires, students, and connections.
Candidates can now complete registration fees through a real payment checkout flow. The integration is signature-verified and webhook-confirmed, meaning activation is only granted after the payment provider confirms receipt — not just on a successful screen. The previous stub behaviour remains the fallback until the live provider is explicitly configured.
Prospective candidates can browse available opportunities on the platform without logging in. Company identities and sensitive details are masked in these public listings, and the pages are indexed by search engines to improve discoverability.
Universities can now link their local departments and courses to a common platform-wide taxonomy. This allows eligibility rules on job requirements to be defined and matched consistently across institutions, without replacing any university's own data.
Every student who had not yet had their CV analysed was incorrectly shown a score of 70/100 with a 'Good match' label. The score is now blank until a real analysis has been run, and the match-tone indicator on screen reflects the actual result.
A defect in the public showcase caused some listings to display unredacted job description text, occasionally including the real company name. The public endpoint now always shows the intended generic description, regardless of what the underlying record contains.
Enabling live payments in the production environment caused the entire API service to crash-loop because the required payment provider configuration had never been committed to the codebase. The configuration has been restored and the service starts cleanly with live payment settings active.
During a brief period of backend instability, visitors clicking into a public opportunity listing were shown a permanent-looking 'not found' page. Only a genuine missing listing now produces that message; any other error prompts the visitor to try again.
A combination of issues meant the rate limit on public opportunity pages was effectively one shared budget for all visitors simultaneously, causing legitimate users to see random access-denied errors. The platform now correctly identifies each visitor's real IP address using a trusted network header, and a separate fix ensures that header cannot be forged by a visitor to claim a fresh budget. Rate limits have also been raised to a level appropriate for normal browsing now that they apply per person rather than site-wide.
A database permissions gap meant that the final step of activating a new independent candidate — creating their account record — failed silently after payment and email verification had already been recorded. Affected candidates had paid ₹499 and completed verification but could not log in, with no automatic recovery path. The activation step now runs with the correct elevated permissions, and the issue has been confirmed resolved against a live database.
Two separate data patterns were causing internship and trainee postings to be incorrectly labelled with top-tier salary bands (e.g. "25+ LPA") on the public opportunities list. The first fix targeted postings that explicitly label their pay as a stipend; the second introduced a plausibility ceiling so that any figure implausibly large to be an annual salary (such as a bare monthly rupee amount with no unit text) is shown as "Not disclosed" rather than a misleading band. Genuine high-salary offers are unaffected.
The opportunities page previously displayed postings in newest-first order using a two-column card grid, making pay comparisons awkward. Roles are now sorted highest pay first, with stipend or undisclosed-pay postings moved to the end. The layout has been changed to a single-column list — role title, type, region, and skills on the left, salary band on the right — making it easier to scan at a glance on both desktop and mobile.
Departments and courses administration with course targeting on requirements, and seven previously hardcoded screens rewired to use it. The NIRF tab, which had displayed fabricated all-zero figures, was replaced with only data the system actually computes.
An unauthenticated remote-code-execution advisory plus seven others. The only externally disclosed vulnerability in the period — everything else here was found internally.
University-wide announcement broadcast with a composer, an internal Posting For field, an Open/Closed filter, the ability to reopen a closed requirement, and a LinkedIn profile link on the candidate header.
An invited sub-admin received no permissions at all until an administrator manually granted them. Now granted at invite, with a backfill for everyone already stuck.
Saving showed no error but changed nothing. The company name also fell back to a hardcoded demo value.
It was quietly falling back to a crude check whenever the AI response was formatted unexpectedly, telling students to add a phone number that was already on their résumé. The dashboard widget was separately showing placeholder values.
Universities can manage the student roster for a drive directly, closing a bug where students could not reliably register or apply. Drives now carry a required-skills list, so match scores reflect what the drive actually asks for.
Photo upload, additional documents, academic semester records, a proof-of-work editor, and a genuine multi-member family details list replacing a single-entry form.
An action on the candidates page was updating the wrong candidate and crashing the Advance step. Résumé preview, broken by an earlier change, was restored.
Sample requirements flashing on page load indistinguishable from real client data, document verification gating, request resolution, rate limiting, requirement validation, PDF export, image uploads and the notification bell.
Invitation emails rate-limited, and institution separation on resend confirmed — an invite can only ever go out under the correct institution.
Saving a company silently downgraded managed institutions and wiped their creation date. Separately, open browser tabs failed every action after a release until reloaded, with nothing telling the user why.
A critical finding closed: candidates could skip stages or reach Hired with no signed offer. Also fixed — adding a company never created its admin account or sent the invite, and publishing a requirement with skills attached failed outright.
AI-generated interview preparation questions, an AI résumé analyzer with a rule-based fallback, semantic match scoring using cached embeddings, and a super-admin AI usage and billing view. Built on an independent AI client with per-call usage logging from day one.
Native interview scheduling with meeting links, a candidate-facing view of scheduled interviews, and in-browser self-introduction video recording.
Fake university statistics, a fabricated platform-health panel, invented impact and compliance report tabs and a placeholder NIRF export were all removed rather than left to mislead. Alongside this: mobile usability repairs across the student, university and admin portals, and a full visual sweep.
Thirty-five findings closed, including several high severity: the Career Passport document vault never returned a working link, university invitations never sent the promised email, offer state was not backed by real closures data, and the Permission Console silently did nothing. Also fixed dashboards freezing after fifteen idle minutes.
A dedicated push to stop the product displaying fabricated identity, pipeline and profile content. Each persona portal was connected to the real backend, and independent-candidate self-registration was added.
Data erasure on request, retention policies, an age gate, and audited release of candidate contact details — a company now has to be granted access rather than simply seeing everyone's details.
Row-level isolation on student data so one institution's records cannot be reached from another, plus a partitioned audit trail recording who accessed what.
Invitations, quotas, consent capture and administrator CSV import; a rules engine for job eligibility; candidate matching and scoring; and a background worker handling mail and notifications reliably rather than inline.
Every file download is now authenticated and authorised, unsigned file links are rejected outright, uploads are validated and rate-limited, and the application refuses to start on a missing or default signing secret. Role guards added for each portal — student, university, company and admin.
A proper identity and roles model replacing a single role field: scope-based permissions enforced endpoint by endpoint across every portal, signed tokens with published verification keys, and rotating refresh tokens that detect and shut down token reuse.
A shared design-token system across the four portals, a component gallery, and a rebuilt marketing landing page.
Secret scanning, code ownership rules, cloud identity federation that removes static access keys entirely, separated database roles, database updates moved out of application startup, and least-privilege deployment permissions. This is the groundwork that makes everything after it safe to change.
Nothing matches those filters.
Release notes
Join. Refer. Earn. — turn your network into rewards.
EzRefer can now send emails via Amazon SES in addition to the existing provider, controlled by a configuration switch. The sending credential is no longer required for the service to start, removing a hard dependency that previously prevented the application from booting without it.
Jobs where the recruiter never set a functional area, industry, job role, or gender were causing errors whenever those jobs were updated or synced from EzRecruit. This is now resolved, and the sync between the two products runs cleanly end-to-end.
Previously, when EzRefer pushed a candidate application back to EzRecruit, it could only send to a single global destination — meaning US-region employers risked having their data sent to the India system. The routing logic now selects the correct regional endpoint based on the job's region. If the US endpoint has not yet been configured, the push is marked as failed and retried automatically once it is set up, rather than silently misdirecting data.
The application now runs any pending database migrations before it starts accepting traffic, eliminating the need for manual intervention during deployments. An additional safeguard ensures the database connection itself is properly time-bounded during this process, preventing deployments from hanging indefinitely.
An internal route used to look up or create company records was returning a server error on every request, even when the underlying operation succeeded. This has been corrected, and the endpoint now returns the expected response reliably.
When a job is created or updated — whether entered directly or synced from an external system — every candidate and referrer is scored for fit and the results are saved. This lays the foundation for targeted notifications and digest emails in upcoming releases.
When a job is created or updated, any candidate whose profile matches that job now receives a notification immediately and automatically. Each candidate is notified exactly once — if the process runs again, no duplicate alerts are sent, and a delivery failure for one candidate does not affect others.
When a weekly digest is sent, any job that scored as a strong match for that recipient is now called out with a 'Recommended for you' section at the top of the email and a badge in the main job list. Candidates with no matches still receive the full digest unchanged. A record is kept of which matches were included so the platform can avoid redundant future notifications.
When a candidate applies on EzRefer to a job that originated in EzRecruit, the application is now forwarded to EzRecruit in the background without any manual step. If the initial attempt fails due to a transient issue, an hourly process retries any stuck or failed submissions automatically, so no applications are silently lost.
The API now returns the information needed for the job detail page to display a 'Synced from EzRecruit' indicator and prevent manual edits to fields that are owned and updated by EzRecruit. This stops locally made changes from being silently overwritten on the next sync.
The platform can now match jobs to candidates and candidates to jobs, covering both sides of the relationship. Candidates receive an instant notification when a strong match is found, and the underlying data structures supporting this are fully live and verified.
When the sync process between EzRecruit and EzRefer rejects a request, the system now logs the specific field-level errors that caused the rejection. This makes it faster to diagnose and resolve the ongoing 422 failures seen during live sync runs.
A gap in the test setup meant the complete suite could never finish — individual tests appeared to pass, masking a failure that only surfaced when all 122 tests ran together. This is now resolved, giving the team a reliable quality gate before any release goes out.
Each deployment was generating a new encryption key, which invalidated any in-flight server-side actions from the previous version. A stable key is now supplied consistently across all deployments, so users no longer experience failures caused by this rotation.
The first live run delivered 512 emails but left no record in monitoring. Delivery was never at risk — every run is recorded in the database — but a nightly job whose successes are invisible cannot be alarmed on.
A nightly digest to candidates and referrers, sending at 20:00 IST, with no backfill flood on first enable.
Reports for super-admins covering clients, candidates and referrers, tenant-scoped reports for enterprise admins and recruiters, and every number on the page clickable through to the underlying detail.
Nothing matches those filters.