Why External Sourcing Should Not Happen In Email Threads
A lot of recruiting teams still handle vendors through off-platform habits. The recruiter emails a role. The agency replies with attachments. Someone manually renames files, tracks provenance in a spreadsheet, and hopes the right people remember which vendor sent which profile. That may work for low volume, but it does not create a reliable sourcing lane.
Ovii is stronger when vendor distribution is described as a governed private channel instead of as another promotion switch. The feature is solving a control problem as much as a sourcing problem. Recruiters need to decide which external partners can work a job, vendors need a constrained place to receive and act on those assignments, and candidate attribution needs to survive once those profiles enter the real pipeline.
That is why the vendor flow matters. It does not just move job information outward. It gives the external sourcing motion a product boundary and an evidence trail.
Ovii treats vendor distribution as a private external sourcing lane with controls, not as a loose job-sharing convenience.
Vendor Access Starts With An Explicit Vendor Identity Model
The first trust signal is that vendors are not treated as anonymous email addresses. The system has a dedicated `Vendor` entity, and the `User` model also includes a vendor relationship for external-vendor accounts. When an invited user completes registration or SSO registration as `EXTERNAL_VENDOR`, the code links that user back to the vendor record.
That linkage matters because later job access and candidate ownership are resolved through it. The recruiter is not sharing a role to a bare inbox. The system is granting job access to a user that belongs to a specific vendor identity inside the company context.
This is exactly the right foundation for a private sourcing channel. A vendor can have a real product identity, while the company still controls whether that vendor is allowed to work a specific role.
| Layer | What the code stores | Why it matters |
|---|---|---|
| Vendor directory | `Vendor` records under the recruiter company | Creates a durable partner identity instead of treating vendors as ad hoc contacts. |
| External vendor user | `User.vendor` plus `vendorId` linkage for `EXTERNAL_VENDOR` accounts | Lets access control and uploads resolve to a specific partner account. |
| Job assignment | `JobVendorMap` between job and vendor | Makes vendor access job-scoped rather than company-wide by default. |
Trusted Vendor Access Is Job-Scoped And Diff-Based
The recruiter-side card is simple, but the backend behavior is more careful than a full reset. When the recruiter saves a vendor list for a job, `JobVendorService` loads the existing mappings, removes only vendors that were deselected, and adds only the newly selected vendors that are not already mapped.
That means the product can update the partner list incrementally instead of destroying and recreating the entire vendor assignment set every time. It is a small detail, but it matters operationally because recruiters often refine the working vendor list as a role evolves.
The card itself also behaves like a governed access surface. If no vendors exist yet, the recruiter is routed back toward vendor setup first. If the toggle is disabled, the job is reassigned with an empty vendor list, which closes the lane for that role.
Ovii updates vendor access by diffing the assigned list, so recruiters can refine partner coverage without creating noisy full resets.
Enabling Vendor Access Is Quota-Aware And Audited
One of the strongest backend details is that vendor access is not treated as a free side effect. When a recruiter enables vendor distribution on a job for the first time, the service checks the company subscription state and enforces the agency-promotion cap. Paid companies reserve quota through the subscription service. Freemium or trial flows are checked against the configured agency-promotion limit.
That makes the feature behave like a governed sourcing resource rather than an unlimited share-everywhere option. If the company is already at its limit for agency-vendor promotion, the enable action can be blocked before the job is opened to another external lane.
The service also writes audit events for enable, disable, and update flows. The logged payload includes job title, vendor count, added vendors, removed vendors, and who made the change. That is exactly the sort of traceability an external-access feature should have.
| Change type | What Ovii checks or logs | Why it matters |
|---|---|---|
| First enable | Agency-promotion cap and subscription path are evaluated. | Prevents vendor distribution from becoming an uncontrolled free channel. |
| Update vendor list | Only added and removed vendors are changed, and the update is audited. | Keeps partner-list changes inspectable. |
| Disable all vendors | All job-vendor mappings can be cleared and a disable audit event is written. | Lets recruiters shut the lane down cleanly for that role. |
Assigned Vendors Get A Separate Job Workspace
Once a vendor is assigned, the job does not need to be re-shared manually through email each time. The vendor-facing API returns all jobs assigned to the logged-in vendor, and the service resolves those jobs through the vendor-to-job mapping. The vendor can also open a full job detail view, but only if the vendor is actually assigned to that role.
This is a better operating model than attaching a PDF job description to an email. The vendor has a dedicated workspace that is already tied to the same product, same role, and same downstream intake pipeline used by the recruiter team.
The vendor job cards also compute vendor-specific candidate counts per job, which reinforces that this workspace is not only a static list of assignments. It is a working surface for external sourcing activity.
Vendors Can Step Away From A Job Without Deleting The Real Job
There is another subtle but useful boundary in the vendor-facing service. A vendor can remove themselves from a job assignment, effectively deleting the position from their own workspace, without affecting the recruiter’s actual job record.
That separation matters because the recruiter owns the role, while the vendor only owns their access to it. If a vendor is no longer working the position, the system should let that vendor stop seeing it without turning that action into job deletion or recruiter-side disruption.
Ovii handles that cleanly by deleting the specific job-vendor mapping rather than the job itself.
Vendor-side removal in Ovii is assignment removal, not job deletion, which keeps recruiter ownership and vendor workspace control separate.
Vendor Upload Uses The Shared Resume Intake Surface, But With Vendor Rules
The vendor upload path is another strong design choice. Vendors use the same `/api/jobs/{jobId}/upload-resumes` endpoint family as other intake flows, but the backend auto-detects external-vendor users and switches the source to `VENDOR_UPLOAD` when appropriate. That keeps the surface consistent without losing source-specific behavior.
Once the source is recognized as `VENDOR_UPLOAD`, the upload is routed into the async RabbitMQ-backed processing flow instead of a fully synchronous path. Files are validated, stored temporarily, wrapped into `VendorResumeProcessingRequestDTO`, and published for downstream processing.
That means vendor submissions are treated like a structured intake stream rather than as a glorified file drop. The vendor gets fast feedback that the resumes are queued, and the heavier parsing, scoring, and embedding work happens asynchronously.
| Step | What the code does | Why it matters |
|---|---|---|
| Source detection | External-vendor users can be auto-routed to `VENDOR_UPLOAD`. | Prevents vendor intake from being mislabeled as recruiter upload. |
| Async routing | `VENDOR_UPLOAD` goes through the async queue when the publisher is available. | Lets vendor sourcing scale without blocking on full enrichment in the request thread. |
| Request validation | The worker validates vendor ID, file type, file size, and temp-file accessibility. | Adds operational safety to partner-submitted files. |
Vendor Candidates Enter The Same Job Workflow With Source Intact
The upload pipeline does not stop at storing files. The vendor resume-processing service creates candidate records, then creates a real `JobApplicationEntity` for the job. When the source is `VENDOR_UPLOAD`, the candidate is attached to the job with the intake code `VENDOR`, resolved through the job-specific status model.
That is an important product detail. Vendor candidates do not bypass the hiring system or land in a separate hidden queue. They enter the same job workflow as other channels, but with vendor provenance preserved on the candidate record.
On the recruiter side, the candidate table maps `VENDOR_UPLOAD` to the source label Vendor, and intake codes such as `VENDOR` are normalized into the same initialized early-state language used elsewhere. That keeps the list readable while still preserving channel truth underneath.
Ovii does not isolate vendor resumes in a side queue. It turns them into real candidates and job applications with `VENDOR_UPLOAD` provenance preserved.
Vendor Ownership Of Candidates Is Narrow On Purpose
Vendor-side candidate access is carefully scoped. To list submitted candidates for a job, the service first checks whether the vendor is assigned to that role. It then fetches only candidates for that job whose source is `VENDOR_UPLOAD` and whose `userId` matches the vendor-linked user.
Deletion is even stricter. A vendor can soft-delete a candidate only if the candidate belongs to the same job, has source `VENDOR_UPLOAD`, and was submitted by that exact vendor user. If any of those checks fail, the deletion is rejected.
This is the right boundary. Vendors can manage the profiles they submitted into the private sourcing lane, but they cannot modify unrelated candidates or rewrite recruiter-owned records.
| Action | Allowed? | Boundary enforced by code |
|---|---|---|
| View assigned jobs | Yes | Vendor must have a job-vendor mapping. |
| Open one assigned job | Yes | Job detail resolves only through the vendor’s assignment. |
| View submitted candidates for that job | Yes | Candidates are filtered to the vendor user and `VENDOR_UPLOAD` source. |
| Delete unrelated candidates | No | Deletion checks job, source, and vendor user ownership before soft-delete. |
Vendor Performance Is Measurable As A Sourcing Lane
One reason this feature is stronger than ad hoc agency sharing is that the vendor lane becomes measurable. The vendor stats service can compute open assigned jobs, candidates submitted in the current versus previous time windows, and average applicants per open job. There is also a job-specific stats service for total, active, and rejected candidate counts per vendor and job.
Some of those metrics are still fairly simple, but the important product point is already there: vendor work is visible as structured activity inside the platform, not as opaque email traffic outside it.
That lets recruiters evaluate vendors by conversion and quality later, not only by raw activity. And it lets vendors see their own working footprint inside the jobs they were actually assigned.
The Better Product Story Here
The help doc explains how to turn vendor access on. The stronger feature story is why this vendor model is trustworthy. Ovii is not just exposing jobs externally. It is anchoring vendor identity in the product, assigning access at the job level, enforcing limits when the lane is first enabled, writing audit events for access changes, constraining vendor job visibility, routing uploads through a source-aware async intake pipeline, and keeping vendor candidate ownership narrow on purpose.
That gives the company a private sourcing lane instead of an inbox dependency. Recruiters keep control over which partners can work which jobs. Vendors get a real workspace for those assignments. Candidates arrive in the same governed pipeline with source intact. And the resulting activity is measurable inside the platform.
That is the story worth publishing, because it shows Ovii is treating vendor distribution as part of the hiring operating system, not as an external sidecar that the team has to remember manually.