Skip to content
VakanssiDocs
VakanssiDocs
Get Vakanssi
esc

Capabilities & roles

A reference for the custom capabilities (12 in the free build, 13 with Pro), the three roles Vakanssi registers, the full role-to-capability matrix, and the AuthorizationPolicy filters.

On this page(9)

Vakanssi defines 13 custom capabilities in the premium build and 12 in the free build, all prefixed vakanssi_, and bundles them into three roles. The one difference is vakanssi_manage_talent_pool, which exists only with Pro Pro feature, requires a Vakanssi Pro license. The split is deliberately granular: reviewers who can move candidates across stages but not delete them, and HR who can export candidate data.

Every capability is a constant on the Vakanssi\Security\Capabilities class; the value is the WordPress capability string a role or user actually holds.

Decisions about a specific application or candidate go through the AuthorizationPolicy service with a semantic action (see The AuthorizationPolicy layer), which is what makes per-object visibility scoping possible without touching every call site. Screen access and simple UI toggles check the capability constant directly with current_user_can().

For a plain-language guide to picking roles for your team, see Roles & permissions.

Capability reference

ConstantCapability stringPurpose
Capabilities::VIEW_APPLICATIONSvakanssi_view_applicationsView the candidate inbox and application records.
Capabilities::EDIT_APPLICATIONvakanssi_edit_applicationEdit an application’s fields and details, and, on Pro, a candidate’s own fields and tags (the edit_candidate action Pro feature, requires a Vakanssi Pro license).
Capabilities::DELETE_APPLICATIONvakanssi_delete_applicationPermanently delete an application.
Capabilities::MANAGE_PIPELINEvakanssi_manage_pipelineConfigure pipeline stages: add, rename, reorder, recolor, retype, and delete.
Capabilities::MOVE_APPLICATIONvakanssi_move_applicationMove a candidate across pipeline stages.
Capabilities::EVALUATE_APPLICATIONvakanssi_evaluate_applicationSet a candidate’s star rating, and submit scorecards Pro feature, requires a Vakanssi Pro license. Since v0.37.0 the star rating is gated here, not on vakanssi_edit_application, so Hiring Manager can rate.
Capabilities::SCHEDULE_INTERVIEWvakanssi_schedule_interviewSchedule, reschedule, or cancel interviews on an application, and propose times for candidate self-booking Pro feature, requires a Vakanssi Pro license.
Capabilities::MANAGE_TALENT_POOL Pro feature, requires a Vakanssi Pro licensevakanssi_manage_talent_poolPremium build only: the constant and the capability do not exist in the free build. Open the Candidates screen (the talent pool): browse, source, and merge candidates. Deleting a person needs vakanssi_delete_application.
Capabilities::COLLABORATEvakanssi_collaboratePost, edit, and delete internal notes (reading them needs only vakanssi_view_applications). With Collaboration Pro feature, requires a Vakanssi Pro license, also @mention and assign applications to teammates.
Capabilities::MANAGE_JOBSvakanssi_manage_jobsCreate, edit, and publish job postings.
Capabilities::VIEW_REPORTSvakanssi_view_reportsView reports and analytics.
Capabilities::EXPORT_DATAvakanssi_export_dataDownload CSV exports: the applications export, plus the Analytics and Candidates exports Pro feature, requires a Vakanssi Pro license. GDPR personal-data exports run through WordPress’s own privacy tools instead.
Capabilities::MANAGE_SETTINGSvakanssi_manage_settingsOpen Settings and Tools, including the Features tab that switches modules on and off.

view_reports is retained but no longer an active gate

Analytics merged into Hiring HQ, which is gated by vakanssi_view_applications. As a result vakanssi_view_reports no longer gates a live screen on its own. The constant and its role grants are kept for backward compatibility and any external consumers, so do not rely on it being removed and do not build new gates on it.

manage_pipeline is granted only alongside manage_settings

The stage editor (Hiring, then Settings, then Pipeline) is gated on vakanssi_manage_pipeline, and the Settings screen that hosts it is itself gated on vakanssi_manage_settings.

Since v0.32.3, Recruiter no longer carries vakanssi_manage_pipeline: only HR / Compliance and Administrator do, and both already hold vakanssi_manage_settings, so every role that can configure stages can also reach the screen that hosts the editor. Before v0.32.3, Recruiter carried vakanssi_manage_pipeline with no reachable screen for it, since Settings itself needs vakanssi_manage_settings.

( new Capabilities() )->all() returns this list in the order above: 13 strings in the premium build, 12 in the free build (all() is an instance method, not a static one). It is the single source of truth for which capabilities this copy of the plugin installs, and it drives role installation.

A companion method, retired(), lists the capabilities the plugin owns but this copy does not install: vakanssi_manage_talent_pool in the free build, nothing in the premium build. Role sync and uninstall remove both lists, so a site that moves from Pro back to free loses the talent-pool capability on its next role sync.

Roles

Vakanssi registers three roles on activation. Each one also receives the WordPress core read capability, so its users can reach wp-admin.

Role keyDisplay nameCapabilities
vakanssi_recruiterRecruiterread plus 9 capabilities (8 in the free build): the full day-to-day toolkit, including managing jobs, the talent pool Pro feature, requires a Vakanssi Pro license, and reports. No pipeline configuration, delete, export, or settings.
vakanssi_hiring_managerHiring Managerread plus 6 capabilities: view, move, evaluate, schedule, collaborate, and view reports.
vakanssi_hrHR / Complianceread plus every Vakanssi capability (13, or 12 in the free build). The only custom role with pipeline configuration, delete, export, and settings access.

Administrator is not a plugin role, but it is granted every Vakanssi capability the build installs directly (see How Administrator stays in control).

Recruiter and HR also hold the core upload_files capability

Since v0.32.3, Recruiter and HR / Compliance, the two roles with vakanssi_manage_jobs, also receive the WordPress core upload_files capability, needed for the job editor’s media library, used to insert images into the job description.

It is a core WordPress capability, not one of the Vakanssi capabilities above, so role installation grants it but never reconciles it away on upgrade. Hiring Manager, which does not manage jobs, does not receive it.

Role installation is idempotent and non-destructive. A missing role is created; the role’s desired capabilities are added; and only plugin-owned capabilities a role should no longer have are removed. Capabilities granted by the site owner or by other plugins are never touched, so upgrades never wipe customizations.

Capability x role matrix

Verified against Capabilities::role_map(). The vakanssi_manage_talent_pool row applies to the premium build only Pro feature, requires a Vakanssi Pro license; the free build has no such capability.

CapabilityRecruiterHiring ManagerHR / ComplianceAdministrator
vakanssi_view_applications✓✓✓✓
vakanssi_edit_application✓✗✓✓
vakanssi_delete_application✗✗✓✓
vakanssi_manage_pipeline✗✗✓✓
vakanssi_move_application✓✓✓✓
vakanssi_evaluate_application✓✓✓✓
vakanssi_schedule_interview✓✓✓✓
vakanssi_manage_talent_pool✓✗✓✓
vakanssi_collaborate✓✓✓✓
vakanssi_manage_jobs✓✗✓✓
vakanssi_view_reports✓✓✓✓
vakanssi_export_data✗✗✓✓
vakanssi_manage_settings✗✗✓✓

In the premium build, Recruiter holds 9 capabilities, Hiring Manager holds 6, and HR / Compliance holds all 13. In the free build, Recruiter holds 8, Hiring Manager 6, and HR / Compliance 12.

How Administrator stays in control

At the end of every role install, every capability the build installs (13, or 12 in the free build) is re-granted to the administrator role, so an upgrade can never lock the site owner out of the ATS. Any retired capability is taken off it in the same pass.

The role map carries its own revision number (Roles::VERSION, currently 5). The vakanssi_roles_version option stores that revision plus a short fingerprint of the installed capability set (for example 5:1a2b3c4d), independently of the plugin version. It syncs in two places:

  • Activation. Roles and capabilities are installed alongside the schema, and the roles revision is stamped.
  • Upgrade. On init and admin_init, when the stored vakanssi_roles_version differs from the shipped revision, roles re-sync automatically and the revision is re-stamped. Because the fingerprint changes with the capability set, switching between the free and premium builds at the same plugin version also triggers a sync. Any request applies it; no reactivation is required.

Legacy roles and capabilities are swept on upgrade

Vakanssi was previously shipped under the wpats and hirepress slugs. Each role sync retires any leftover wpats_* / hirepress_* roles (users still holding one are reassigned to the current equivalent first, so a rename never strips anyone of access) and removes any capability whose name contains one of those brand tokens from every role. Third-party capabilities are never affected.

Uninstalling the plugin removes the three roles and strips all 13 capabilities from Administrator. See Database schema for the full uninstall behavior.

The AuthorizationPolicy layer

Vakanssi\Security\AuthorizationPolicy is the single decision point for “can this user perform this action on this object?”. Feature code asks it with a semantic action:

// $authz is the AuthorizationPolicy service.
$authz->can( $user, 'move_application', $application_id );

can() maps the action to its capability, checks it, then passes the decision through a filter. That gives one place to add object-level scoping (assigned applications, hiring teams) without rewriting call sites. Bulk operations route every selected object through filter_allowed( $user, $action, $objects ), so per-object scoping is honored item by item. In the premium build, collection queries (the inbox, the board’s REST list) also call application_scope() for SQL-level narrowing.

Five public filters expose this layer. vakanssi/authz/can and vakanssi/authz/action_map exist in both builds. The three scoping filters, vakanssi/authz/application_scope, vakanssi/authz/candidate_scope, and vakanssi/authz/visible_applications, fire only in the premium build Pro feature, requires a Vakanssi Pro license: the free build ships neither the methods nor any SQL taken from a filter, so its lists stay organization-wide.

A premium site adding its own scoping has to answer all three scoping filters, or the board narrows while the talent pool and candidate profiles stay organization-wide.

vakanssi/authz/can

apply_filters( 'vakanssi/authz/can', $allowed, $action, $object, $user, $capability );

$allowed (bool) is the capability-level decision; $action (string) is the semantic action, for example move_application; $object (mixed) is the optional subject id; $user is an int, a WP_User, or null for the current user; $capability (string or null) is the mapped capability. Return false to deny even when the capability is held. This filter should only ever tighten a decision, never grant access the capability layer denied.

vakanssi/authz/application_scope Pro feature, requires a Vakanssi Pro license

Premium build only. The free build does not fire this filter, so a callback added there never runs.

apply_filters(
    'vakanssi/authz/application_scope',
    array( 'clauses' => array(), 'params' => array() ),
    $user
);

The collection-level companion to can(): return extra SQL WHERE fragments plus their prepared parameters to narrow application listings. Fragments must reference the a. (applications) table alias, and every %s / %d placeholder needs a matching entry in params, in order.

Restrict a non-privileged user to a single job’s applications, letting the “manage settings” tier (administrators and HR) keep seeing everything:

add_filter( 'vakanssi/authz/application_scope', function ( $scope, $user_id ) {
    if ( user_can( $user_id, 'vakanssi_manage_settings' ) ) {
        return $scope; // Administrators and HR see everything.
    }

    $scope['clauses'][] = 'a.job_id = %d';
    $scope['params'][]  = 42; // Only this job's applications.

    return $scope;
}, 10, 2 );

The Pro Collaboration module’s assignment visibility is built entirely on this filter and vakanssi/authz/can: when its “assignment visibility” setting is on, it adds the fragment (a.assigned_to = %d OR a.assigned_to = 0) for staff who cannot manage settings, so recruiters and hiring managers only see applications assigned to them or still unassigned. It is proof the seam works without core changes.

vakanssi/authz/candidate_scope and vakanssi/authz/visible_applications Pro feature, requires a Vakanssi Pro license

Premium build only, like application_scope: the free build fires neither filter.

apply_filters(
    'vakanssi/authz/candidate_scope',
    array( 'clauses' => array(), 'params' => array() ),
    $user
);
apply_filters( 'vakanssi/authz/visible_applications', $application_ids, $user );

candidate_scope is the candidate-level companion to application_scope: the same clauses / params shape, but fragments reference the c. (candidates) alias, and it narrows the Candidates list Pro feature, requires a Vakanssi Pro license, its bulk actions, and the candidates CSV export.

visible_applications receives an array of application ids and a user id, and returns the subset that user may see. It trims a candidate profile’s application history, where the ids are already in hand. Order is preserved.

vakanssi/authz/action_map

apply_filters( 'vakanssi/authz/action_map', $map );

Filters the semantic-action to capability map: 16 default entries in the premium build, 12 in the free build. The map is cached per policy instance: the shared instance reads it at the first authorization check, and a few code paths build their own instance. Add the filter on plugins_loaded or init, before any authorization check runs; a filter added later reaches some surfaces and not others.

In the free build all 12 mirror the capabilities one for one. The premium build adds four talent-pool actions Pro feature, requires a Vakanssi Pro license: manage_talent_pool, which mirrors its capability, and three that do not, all deliberate. view_candidate maps to vakanssi_manage_talent_pool, and delete_candidate maps to vakanssi_delete_application, because destroying a person cascades to their applications and files.

edit_candidate gates writing to a person’s own fields, tags, and job attachments, and maps to vakanssi_edit_application rather than the talent-pool capability, so a site can grant browse-only talent-pool access separately from the ability to edit what is in it.

Useful to route a custom action through an existing capability:

add_filter( 'vakanssi/authz/action_map', function ( array $map ) {
    $map['export_candidates'] = 'vakanssi_export_data';
    return $map;
} );

For the full extension pattern, see Extending safely and the Hooks reference.