@dakkitor/api-contracts 1.8.0 → 1.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abilities/abilities.contract.d.ts +28 -1
- package/dist/abilities/abilities.contract.d.ts.map +1 -1
- package/dist/abilities/abilities.contract.js +32 -1
- package/dist/abilities/abilities.contract.spec.js +63 -3
- package/dist/abilities/admin-dashboard.abilities.test.js +1 -0
- package/dist/abilities/automatic-caller.abilities.json +1 -0
- package/dist/abilities/first-agent.abilities.json +14 -0
- package/dist/abilities/interconnection.abilities.json +17 -1
- package/dist/abilities/office-manager.abilities.json +4 -0
- package/dist/abilities/second-agent.abilities.json +48 -1
- package/dist/abilities/worker-curator.abilities.json +17 -1
- package/dist/actives/actives.contract.d.ts +6959 -6547
- package/dist/actives/actives.contract.d.ts.map +1 -1
- package/dist/agent-client-links/agent-client-links.contract.d.ts +1275 -1173
- package/dist/agent-client-links/agent-client-links.contract.d.ts.map +1 -1
- package/dist/auth/auth.contract.d.ts +102 -102
- package/dist/bookings/backdate-guard.spec.js +24 -32
- package/dist/bookings/bookings.contract.d.ts +9963 -9305
- package/dist/bookings/bookings.contract.d.ts.map +1 -1
- package/dist/bookings/bookings.contract.js +2 -16
- package/dist/call-history/call-history.contract.d.ts +1040 -828
- package/dist/call-history/call-history.contract.d.ts.map +1 -1
- package/dist/calls-feed/calls-feed.contract.d.ts +138 -98
- package/dist/calls-feed/calls-feed.contract.d.ts.map +1 -1
- package/dist/candidate-calling/candidate-calling.contract.d.ts +18372 -0
- package/dist/candidate-calling/candidate-calling.contract.d.ts.map +1 -0
- package/dist/candidate-calling/candidate-calling.contract.js +494 -0
- package/dist/candidate-calling/candidate-calling.contract.spec.d.ts +2 -0
- package/dist/candidate-calling/candidate-calling.contract.spec.d.ts.map +1 -0
- package/dist/candidate-calling/candidate-calling.contract.spec.js +357 -0
- package/dist/candidate-calling/candidate-dialpad-call.schemas.d.ts +10 -0
- package/dist/candidate-calling/candidate-dialpad-call.schemas.d.ts.map +1 -0
- package/dist/candidate-calling/candidate-dialpad-call.schemas.js +33 -0
- package/dist/client-contacts/client-contacts.contract.d.ts +622 -622
- package/dist/clients/clients.contract.d.ts +289 -289
- package/dist/collaboration-checkings/collaboration-checkings.contract.d.ts +3108 -3004
- package/dist/collaboration-checkings/collaboration-checkings.contract.d.ts.map +1 -1
- package/dist/collaborations/collaborations.contract.d.ts +2604 -2507
- package/dist/collaborations/collaborations.contract.d.ts.map +1 -1
- package/dist/common/callback-slots.d.ts +4 -0
- package/dist/common/callback-slots.d.ts.map +1 -0
- package/dist/common/callback-slots.js +20 -0
- package/dist/common/common-schemas.d.ts +10 -4
- package/dist/common/common-schemas.d.ts.map +1 -1
- package/dist/common/common-schemas.js +6 -0
- package/dist/companies/companies.contract.d.ts +120 -120
- package/dist/crews/crews.contract.d.ts +278 -278
- package/dist/cron-executions/cron-executions.contract.d.ts +245 -245
- package/dist/cron-executions/cron-executions.contract.d.ts.map +1 -1
- package/dist/cron-executions/cron-executions.contract.js +1 -0
- package/dist/curated-worker-leads/candidate-coordination.contract.d.ts +3830 -2354
- package/dist/curated-worker-leads/candidate-coordination.contract.d.ts.map +1 -1
- package/dist/curated-worker-leads/candidate-coordination.contract.js +73 -7
- package/dist/curated-worker-leads/candidate-edit-session.contract.d.ts +94 -94
- package/dist/curated-worker-leads/contact-history.spec.js +141 -0
- package/dist/curated-worker-leads/job-candidate-cards.spec.js +19 -0
- package/dist/curated-worker-leads/job-candidates.spec.js +179 -0
- package/dist/curated-worker-leads/jobs-tab.contract.d.ts +8185 -2106
- package/dist/curated-worker-leads/jobs-tab.contract.d.ts.map +1 -1
- package/dist/curated-worker-leads/jobs-tab.contract.js +126 -1
- package/dist/curated-worker-leads/owned-jobs-tab.contract.d.ts +110 -110
- package/dist/curated-workers/curated-workers.contract.d.ts +2033 -1951
- package/dist/curated-workers/curated-workers.contract.d.ts.map +1 -1
- package/dist/dashboards/dashboard-widgets.contact-history.spec.d.ts +2 -0
- package/dist/dashboards/dashboard-widgets.contact-history.spec.d.ts.map +1 -0
- package/dist/dashboards/dashboard-widgets.contact-history.spec.js +160 -0
- package/dist/dashboards/dashboard-widgets.contract.d.ts +1027 -284
- package/dist/dashboards/dashboard-widgets.contract.d.ts.map +1 -1
- package/dist/dashboards/dashboard-widgets.contract.js +46 -1
- package/dist/dashboards/dashboard.contract.d.ts +8 -8
- package/dist/document-intake/document-intake.contract.d.ts +1145 -1145
- package/dist/export-jobs/export-jobs.contract.d.ts +755 -755
- package/dist/exports-events/exports-events.schemas.d.ts +6 -6
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/jobs/jobs.contract.d.ts +8507 -6044
- package/dist/jobs/jobs.contract.d.ts.map +1 -1
- package/dist/jobs/jobs.contract.js +95 -2
- package/dist/jobs/jobs.contract.spec.js +231 -1
- package/dist/kpi-impersonation/kpi-impersonation.contract.d.ts +102 -102
- package/dist/lead-assignments/lead-assignments.contract.d.ts +2985 -1139
- package/dist/lead-assignments/lead-assignments.contract.d.ts.map +1 -1
- package/dist/lead-assignments/lead-assignments.contract.js +102 -2
- package/dist/lead-assignments/lead-assignments.contract.spec.d.ts +2 -0
- package/dist/lead-assignments/lead-assignments.contract.spec.d.ts.map +1 -0
- package/dist/lead-assignments/lead-assignments.contract.spec.js +51 -0
- package/dist/lead-distribution/agent-lead-distribution.contract.d.ts +341 -317
- package/dist/lead-distribution/agent-lead-distribution.contract.d.ts.map +1 -1
- package/dist/leads/leads.contract.d.ts +282 -282
- package/dist/locations/location-enrichment.contract.spec.d.ts +2 -0
- package/dist/locations/location-enrichment.contract.spec.d.ts.map +1 -0
- package/dist/locations/location-enrichment.contract.spec.js +50 -0
- package/dist/locations/locations.contract.d.ts +132 -98
- package/dist/locations/locations.contract.d.ts.map +1 -1
- package/dist/locations/locations.contract.js +10 -0
- package/dist/notifications/notifications.contract.d.ts +579 -107
- package/dist/notifications/notifications.contract.d.ts.map +1 -1
- package/dist/notifications/notifications.contract.js +36 -2
- package/dist/notifications/notifications.contract.spec.d.ts +2 -0
- package/dist/notifications/notifications.contract.spec.d.ts.map +1 -0
- package/dist/notifications/notifications.contract.spec.js +39 -0
- package/dist/outreach/__tests__/outreach-claim.test.js +33 -0
- package/dist/outreach/__tests__/outreach-routes.test.js +8 -0
- package/dist/outreach/outreach.contract.d.ts +583 -162
- package/dist/outreach/outreach.contract.d.ts.map +1 -1
- package/dist/outreach/outreach.contract.js +50 -1
- package/dist/outreach/relay-hub-outreach.contract.d.ts +299 -121
- package/dist/outreach/relay-hub-outreach.contract.d.ts.map +1 -1
- package/dist/outreach/relay-hub-outreach.contract.js +10 -0
- package/dist/outreach/relay-hub-outreach.contract.spec.js +26 -0
- package/dist/outreach/relay-hub-outreach.schemas.d.ts +94 -0
- package/dist/outreach/relay-hub-outreach.schemas.d.ts.map +1 -0
- package/dist/outreach/relay-hub-outreach.schemas.js +15 -0
- package/dist/own-research/check-phone-response.spec.d.ts +2 -0
- package/dist/own-research/check-phone-response.spec.d.ts.map +1 -0
- package/dist/own-research/check-phone-response.spec.js +54 -0
- package/dist/own-research/own-research.contract.d.ts +971 -820
- package/dist/own-research/own-research.contract.d.ts.map +1 -1
- package/dist/own-research/own-research.contract.js +6 -1
- package/dist/proofs/proofs.contract.d.ts +356 -356
- package/dist/proofs/proofs.dtos.d.ts +148 -148
- package/dist/realtime/job-call-priority-updated.d.ts +18 -0
- package/dist/realtime/job-call-priority-updated.d.ts.map +1 -0
- package/dist/realtime/job-call-priority-updated.js +17 -0
- package/dist/shared/summary-schemas.d.ts +36 -27
- package/dist/shared/summary-schemas.d.ts.map +1 -1
- package/dist/shared/summary-schemas.js +7 -0
- package/dist/sheets-sync/sheets-sync.contract.d.ts +683 -683
- package/dist/user-access-grants/user-access-grants.contract.d.ts +216 -216
- package/dist/users/users.contract.d.ts +365 -336
- package/dist/users/users.contract.d.ts.map +1 -1
- package/dist/users/users.contract.js +9 -1
- package/dist/users/users.contract.spec.js +39 -0
- package/dist/worker-source-identity-conflicts/worker-source-identity-conflicts.contract.d.ts +150 -150
- package/dist/workers/workers.contract.d.ts +4505 -4261
- package/dist/workers/workers.contract.d.ts.map +1 -1
- package/dist/workers/workers.contract.js +12 -0
- package/package.json +1 -1
|
@@ -14,6 +14,7 @@ export interface AbilityRule {
|
|
|
14
14
|
inverted?: boolean;
|
|
15
15
|
}
|
|
16
16
|
export declare const AdminAbilities: AbilityRule[];
|
|
17
|
+
export declare const AutomaticCallerAbilities: AbilityRule[];
|
|
17
18
|
export declare const KpiAbilities: AbilityRule[];
|
|
18
19
|
export declare const FirstAgentAbilities: AbilityRule[];
|
|
19
20
|
export declare const SecondAgentAbilities: AbilityRule[];
|
|
@@ -38,6 +39,7 @@ export declare const RoleAbilities: {
|
|
|
38
39
|
readonly WORKER_CURATOR: AbilityRule[];
|
|
39
40
|
readonly INTERCONNECTION: AbilityRule[];
|
|
40
41
|
readonly OUTREACH: AbilityRule[];
|
|
42
|
+
readonly AUTOMATIC_CALLER: AbilityRule[];
|
|
41
43
|
};
|
|
42
44
|
export type RoleAbilitiesType = typeof RoleAbilities;
|
|
43
45
|
/**
|
|
@@ -46,7 +48,7 @@ export type RoleAbilitiesType = typeof RoleAbilities;
|
|
|
46
48
|
* Kept in sync with the abilities JSON files by abilities.contract.spec.ts,
|
|
47
49
|
* which fails on any JSON subject missing from the known-subject registry.
|
|
48
50
|
*/
|
|
49
|
-
export declare const VIRTUAL_SUBJECTS: readonly ["FaDashboardWidgets", "SaDashboardWidgets", "DashboardTrends", "AdminFaDashboardWidgets", "AdminSaDashboardWidgets", "AdminAgentStats", "AdminProofs", "AdminDashboardTrends", "FirstAgentTutorials", "CuratedMatchWorkspace", "JobCandidate", "LeadActivityEvent", "FilterCandidateContactHistorySchema", "SecondAgentTutorials", "SortActiveSchema", "SortBookingSchema", "SortJobSchema", "SortWorkerSchema", "SortCuratedWorkerSchema", "SortLeadSchema", "SortOwnResearchLeadSchema", "SortClientSchema", "SortCompanySchema", "SortCollaborationSchema", "SortCollaborationCheckingSchema", "SortClientContactSchema", "SortCallHistorySchema", "SortUserSchema", "SortCrewSchema", "FilterExportJobSchema", "OutreachClaim", "OutreachRequest", "RelayPod"];
|
|
51
|
+
export declare const VIRTUAL_SUBJECTS: readonly ["FaDashboardWidgets", "SaDashboardWidgets", "DashboardTrends", "AdminSharedDashboardWidgets", "AdminFaDashboardWidgets", "AdminSaDashboardWidgets", "AdminAgentStats", "AdminProofs", "AdminDashboardTrends", "FirstAgentTutorials", "CuratedMatchWorkspace", "JobCandidate", "CandidateCallingQueue", "LeadActivityEvent", "FilterCandidateContactHistorySchema", "SecondAgentTutorials", "SortActiveSchema", "SortBookingSchema", "SortJobSchema", "SortWorkerSchema", "SortCuratedWorkerSchema", "SortLeadSchema", "SortOwnResearchLeadSchema", "SortClientSchema", "SortCompanySchema", "SortCollaborationSchema", "SortCollaborationCheckingSchema", "SortClientContactSchema", "SortCallHistorySchema", "SortUserSchema", "SortCrewSchema", "FilterExportJobSchema", "OutreachClaim", "OutreachRequest", "RelayPod"];
|
|
50
52
|
export type VirtualSubjects = (typeof VIRTUAL_SUBJECTS)[number];
|
|
51
53
|
/**
|
|
52
54
|
* Roles an OFFICE_MANAGER may assign to users they create.
|
|
@@ -61,7 +63,32 @@ export declare const OFFICE_MANAGER_ASSIGNABLE_ROLES: readonly ["FIRST_AGENT", "
|
|
|
61
63
|
* inverted ability rule never fires for an admin-who-is-also-an-OM.
|
|
62
64
|
*/
|
|
63
65
|
export declare function getRolesOmCannotAssign(actingUserRoles: readonly UserRole[] | undefined): UserRole[];
|
|
66
|
+
/**
|
|
67
|
+
* Deliberately does NOT list AUTOMATIC_CALLER even though
|
|
68
|
+
* `hasSharedCuratedMatchAccess` recognises it. This constant is typed against
|
|
69
|
+
* `UserRole`, which is the ASSIGNABLE role list — service roles (BOT,
|
|
70
|
+
* CRON_SCHEDULER, OUTREACH_SERVICE, AUTOMATIC_CALLER) are all absent from it
|
|
71
|
+
* by design, because no human may hand one out through the users API. Use the
|
|
72
|
+
* function, not this list, to ask whether a viewer has the access.
|
|
73
|
+
*/
|
|
64
74
|
export declare const SHARED_CURATED_MATCH_ROLES: readonly ["ADMIN", "WORKER_CURATOR", "INTERCONNECTION"];
|
|
75
|
+
/**
|
|
76
|
+
* AUTOMATIC_CALLER is here because the reachability prober is a genuine
|
|
77
|
+
* shared-curated-match viewer: it ranks jobs and candidates through exactly
|
|
78
|
+
* the same `job_call_priority_scores` rows and the same candidate-eligibility
|
|
79
|
+
* SQL an agent does, and BOTH refuse a viewer without this access —
|
|
80
|
+
* `eligibleCandidateBulkSql` degrades to a hard-coded `FALSE`, and
|
|
81
|
+
* `JobCallPriorityRefreshProcessor` DELETES the viewer's scores. Stating it
|
|
82
|
+
* once here keeps the ranking, the refresh and the driver in agreement;
|
|
83
|
+
* the alternative was borrowing WORKER_CURATOR at the driver's call sites,
|
|
84
|
+
* which is both a lie about the seat and two copies to drift apart.
|
|
85
|
+
*
|
|
86
|
+
* This widens NO authenticated surface. The seat's password is `no-login`, it
|
|
87
|
+
* holds no abilities (`automatic-caller.abilities.json` is `[]`), and it is
|
|
88
|
+
* excluded from every user roster by HIDDEN_SERVICE_ROLES — so the only code
|
|
89
|
+
* that can ever present these roles is server-side code that constructs them
|
|
90
|
+
* from the constant on purpose.
|
|
91
|
+
*/
|
|
65
92
|
export declare function hasSharedCuratedMatchAccess(roles: readonly string[] | null | undefined): boolean;
|
|
66
93
|
/**
|
|
67
94
|
* Roles whose JOB-FIRST CANDIDATE scope is global: inside a specific job's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abilities.contract.d.ts","sourceRoot":"","sources":["../../contracts/abilities/abilities.contract.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"abilities.contract.d.ts","sourceRoot":"","sources":["../../contracts/abilities/abilities.contract.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAeH,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,cAAc,EAAE,WAAW,EAAoC,CAAC;AAC7E,eAAO,MAAM,wBAAwB,EAAE,WAAW,EACP,CAAC;AAC5C,eAAO,MAAM,YAAY,EAAE,WAAW,EAAkC,CAAC;AACzE,eAAO,MAAM,mBAAmB,EAAE,WAAW,EACP,CAAC;AACvC,eAAO,MAAM,oBAAoB,EAAE,WAAW,EACP,CAAC;AACxC,eAAO,MAAM,iBAAiB,EAAE,WAAW,EACP,CAAC;AACrC,eAAO,MAAM,YAAY,EAAE,WAAW,EAAkC,CAAC;AACzE,eAAO,MAAM,sBAAsB,EAAE,WAAW,EACP,CAAC;AAC1C,eAAO,MAAM,wBAAwB,EAAE,WAAW,EACP,CAAC;AAC5C,eAAO,MAAM,sBAAsB,EAAE,WAAW,EACP,CAAC;AAC1C,eAAO,MAAM,sBAAsB,EAAE,WAAW,EACP,CAAC;AAC1C,eAAO,MAAM,wBAAwB,EAAE,WAAW,EACP,CAAC;AAC5C,eAAO,MAAM,iBAAiB,EAAE,WAAW,EACP,CAAC;AAErC,eAAO,MAAM,aAAa;;;;;;;;;;;;;;CAchB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,OAAO,aAAa,CAAC;AAErD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,syBAoCnB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE;;;GAGG;AACH,eAAO,MAAM,+BAA+B,0CAGJ,CAAC;AAEzC;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,eAAe,EAAE,SAAS,QAAQ,EAAE,GAAG,SAAS,GAC/C,QAAQ,EAAE,CAMZ;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,yDAIC,CAAC;AAWzC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAST;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,0BAA0B,uCAGC,CAAC;AAEzC;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAIT;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAMT"}
|
|
@@ -10,12 +10,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
10
10
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.GLOBAL_CURATED_SCOPE_ROLES = exports.SHARED_CURATED_MATCH_ROLES = exports.OFFICE_MANAGER_ASSIGNABLE_ROLES = exports.VIRTUAL_SUBJECTS = exports.RoleAbilities = exports.OutreachAbilities = exports.InterconnectionAbilities = exports.WorkerCuratorAbilities = exports.OfficeManagerAbilities = exports.OutreachServiceAbilities = exports.CronSchedulerAbilities = exports.BotAbilities = exports.TeamLeadAbilities = exports.SecondAgentAbilities = exports.FirstAgentAbilities = exports.KpiAbilities = exports.AdminAbilities = void 0;
|
|
13
|
+
exports.GLOBAL_CURATED_SCOPE_ROLES = exports.SHARED_CURATED_MATCH_ROLES = exports.OFFICE_MANAGER_ASSIGNABLE_ROLES = exports.VIRTUAL_SUBJECTS = exports.RoleAbilities = exports.OutreachAbilities = exports.InterconnectionAbilities = exports.WorkerCuratorAbilities = exports.OfficeManagerAbilities = exports.OutreachServiceAbilities = exports.CronSchedulerAbilities = exports.BotAbilities = exports.TeamLeadAbilities = exports.SecondAgentAbilities = exports.FirstAgentAbilities = exports.KpiAbilities = exports.AutomaticCallerAbilities = exports.AdminAbilities = void 0;
|
|
14
14
|
exports.getRolesOmCannotAssign = getRolesOmCannotAssign;
|
|
15
15
|
exports.hasSharedCuratedMatchAccess = hasSharedCuratedMatchAccess;
|
|
16
16
|
exports.hasGlobalCuratedCandidateScope = hasGlobalCuratedCandidateScope;
|
|
17
17
|
exports.isCandidateOnlyCuratedViewer = isCandidateOnlyCuratedViewer;
|
|
18
18
|
const admin_abilities_json_1 = __importDefault(require("./admin.abilities.json"));
|
|
19
|
+
const automatic_caller_abilities_json_1 = __importDefault(require("./automatic-caller.abilities.json"));
|
|
19
20
|
const bot_abilities_json_1 = __importDefault(require("./bot.abilities.json"));
|
|
20
21
|
const cron_scheduler_abilities_json_1 = __importDefault(require("./cron-scheduler.abilities.json"));
|
|
21
22
|
const first_agent_abilities_json_1 = __importDefault(require("./first-agent.abilities.json"));
|
|
@@ -29,6 +30,7 @@ const interconnection_abilities_json_1 = __importDefault(require("./interconnect
|
|
|
29
30
|
const outreach_abilities_json_1 = __importDefault(require("./outreach.abilities.json"));
|
|
30
31
|
const users_contract_1 = require("../users/users.contract");
|
|
31
32
|
exports.AdminAbilities = admin_abilities_json_1.default;
|
|
33
|
+
exports.AutomaticCallerAbilities = automatic_caller_abilities_json_1.default;
|
|
32
34
|
exports.KpiAbilities = kpi_abilities_json_1.default;
|
|
33
35
|
exports.FirstAgentAbilities = first_agent_abilities_json_1.default;
|
|
34
36
|
exports.SecondAgentAbilities = second_agent_abilities_json_1.default;
|
|
@@ -53,6 +55,7 @@ exports.RoleAbilities = {
|
|
|
53
55
|
WORKER_CURATOR: exports.WorkerCuratorAbilities,
|
|
54
56
|
INTERCONNECTION: exports.InterconnectionAbilities,
|
|
55
57
|
OUTREACH: exports.OutreachAbilities,
|
|
58
|
+
AUTOMATIC_CALLER: exports.AutomaticCallerAbilities,
|
|
56
59
|
};
|
|
57
60
|
/**
|
|
58
61
|
* Virtual subjects that don't correspond to entity classes.
|
|
@@ -64,6 +67,7 @@ exports.VIRTUAL_SUBJECTS = [
|
|
|
64
67
|
'FaDashboardWidgets',
|
|
65
68
|
'SaDashboardWidgets',
|
|
66
69
|
'DashboardTrends',
|
|
70
|
+
'AdminSharedDashboardWidgets',
|
|
67
71
|
'AdminFaDashboardWidgets',
|
|
68
72
|
'AdminSaDashboardWidgets',
|
|
69
73
|
'AdminAgentStats',
|
|
@@ -72,6 +76,7 @@ exports.VIRTUAL_SUBJECTS = [
|
|
|
72
76
|
'FirstAgentTutorials',
|
|
73
77
|
'CuratedMatchWorkspace',
|
|
74
78
|
'JobCandidate',
|
|
79
|
+
'CandidateCallingQueue',
|
|
75
80
|
'LeadActivityEvent',
|
|
76
81
|
'FilterCandidateContactHistorySchema',
|
|
77
82
|
'SecondAgentTutorials',
|
|
@@ -117,6 +122,14 @@ function getRolesOmCannotAssign(actingUserRoles) {
|
|
|
117
122
|
const allowed = new Set(exports.OFFICE_MANAGER_ASSIGNABLE_ROLES);
|
|
118
123
|
return users_contract_1.UserRoleSchema.options.filter((role) => !allowed.has(role));
|
|
119
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Deliberately does NOT list AUTOMATIC_CALLER even though
|
|
127
|
+
* `hasSharedCuratedMatchAccess` recognises it. This constant is typed against
|
|
128
|
+
* `UserRole`, which is the ASSIGNABLE role list — service roles (BOT,
|
|
129
|
+
* CRON_SCHEDULER, OUTREACH_SERVICE, AUTOMATIC_CALLER) are all absent from it
|
|
130
|
+
* by design, because no human may hand one out through the users API. Use the
|
|
131
|
+
* function, not this list, to ask whether a viewer has the access.
|
|
132
|
+
*/
|
|
120
133
|
exports.SHARED_CURATED_MATCH_ROLES = [
|
|
121
134
|
'ADMIN',
|
|
122
135
|
'WORKER_CURATOR',
|
|
@@ -126,11 +139,29 @@ function hasInterconnectionModifierPair(roles) {
|
|
|
126
139
|
return (roles?.includes('SECOND_AGENT') === true &&
|
|
127
140
|
roles.includes('INTERCONNECTION'));
|
|
128
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* AUTOMATIC_CALLER is here because the reachability prober is a genuine
|
|
144
|
+
* shared-curated-match viewer: it ranks jobs and candidates through exactly
|
|
145
|
+
* the same `job_call_priority_scores` rows and the same candidate-eligibility
|
|
146
|
+
* SQL an agent does, and BOTH refuse a viewer without this access —
|
|
147
|
+
* `eligibleCandidateBulkSql` degrades to a hard-coded `FALSE`, and
|
|
148
|
+
* `JobCallPriorityRefreshProcessor` DELETES the viewer's scores. Stating it
|
|
149
|
+
* once here keeps the ranking, the refresh and the driver in agreement;
|
|
150
|
+
* the alternative was borrowing WORKER_CURATOR at the driver's call sites,
|
|
151
|
+
* which is both a lie about the seat and two copies to drift apart.
|
|
152
|
+
*
|
|
153
|
+
* This widens NO authenticated surface. The seat's password is `no-login`, it
|
|
154
|
+
* holds no abilities (`automatic-caller.abilities.json` is `[]`), and it is
|
|
155
|
+
* excluded from every user roster by HIDDEN_SERVICE_ROLES — so the only code
|
|
156
|
+
* that can ever present these roles is server-side code that constructs them
|
|
157
|
+
* from the constant on purpose.
|
|
158
|
+
*/
|
|
129
159
|
function hasSharedCuratedMatchAccess(roles) {
|
|
130
160
|
if (!roles)
|
|
131
161
|
return false;
|
|
132
162
|
return (roles.includes('ADMIN') ||
|
|
133
163
|
roles.includes('WORKER_CURATOR') ||
|
|
164
|
+
roles.includes('AUTOMATIC_CALLER') ||
|
|
134
165
|
hasInterconnectionModifierPair(roles));
|
|
135
166
|
}
|
|
136
167
|
/**
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const abilities_contract_1 = require("./abilities.contract");
|
|
4
|
+
const users_contract_1 = require("../users/users.contract");
|
|
4
5
|
/**
|
|
5
6
|
* Entity subjects the API resolves through SUBJECT_CLASS_MAP
|
|
6
7
|
* (apps/api/src/modules/casl/casl-ability.factory.ts). Mirrored here because
|
|
@@ -29,6 +30,7 @@ const ENTITY_SUBJECTS = [
|
|
|
29
30
|
'Job',
|
|
30
31
|
'Lead',
|
|
31
32
|
'LeadAssignment',
|
|
33
|
+
'LeadCallback',
|
|
32
34
|
'Location',
|
|
33
35
|
'Office',
|
|
34
36
|
'OwnResearchLead',
|
|
@@ -95,6 +97,21 @@ describe('abilities JSON subject validity', () => {
|
|
|
95
97
|
expect(violations).toEqual([]);
|
|
96
98
|
});
|
|
97
99
|
});
|
|
100
|
+
describe('candidate calling queue grants', () => {
|
|
101
|
+
it('registers the virtual subject and grants SECOND_AGENT queue control', () => {
|
|
102
|
+
expect(abilities_contract_1.VIRTUAL_SUBJECTS).toContain('CandidateCallingQueue');
|
|
103
|
+
expect(abilities_contract_1.SecondAgentAbilities.filter((rule) => rule.subject === 'CandidateCallingQueue')).toEqual([
|
|
104
|
+
{ action: 'read', subject: 'CandidateCallingQueue' },
|
|
105
|
+
{ action: 'create', subject: 'CandidateCallingQueue' },
|
|
106
|
+
{ action: 'update', subject: 'CandidateCallingQueue' },
|
|
107
|
+
{ action: 'delete', subject: 'CandidateCallingQueue' },
|
|
108
|
+
]);
|
|
109
|
+
});
|
|
110
|
+
it('lets SECOND_AGENT receive aggregate job call-priority fields', () => {
|
|
111
|
+
const jobReadRule = abilities_contract_1.SecondAgentAbilities.find((rule) => rule.action === 'read' && rule.subject === 'Job');
|
|
112
|
+
expect(jobReadRule?.fields).toEqual(expect.arrayContaining(['callPriority', 'callPriority.*']));
|
|
113
|
+
});
|
|
114
|
+
});
|
|
98
115
|
describe('Relay pod membership grants', () => {
|
|
99
116
|
it('grants no RelayPod authority; pod access comes from membership', () => {
|
|
100
117
|
const relayPodRules = abilities_contract_1.OutreachAbilities.filter((rule) => rule.subject === 'RelayPod');
|
|
@@ -133,10 +150,34 @@ describe('shared curated match access', () => {
|
|
|
133
150
|
[['FIRST_AGENT', 'INTERCONNECTION'], false],
|
|
134
151
|
[['SECOND_AGENT'], false],
|
|
135
152
|
[['FIRST_AGENT'], false],
|
|
153
|
+
[['AUTOMATIC_CALLER'], true],
|
|
136
154
|
[[], false],
|
|
137
155
|
])('%j => %s', (roles, expected) => {
|
|
138
156
|
expect((0, abilities_contract_1.hasSharedCuratedMatchAccess)(roles)).toBe(expected);
|
|
139
157
|
});
|
|
158
|
+
/**
|
|
159
|
+
* AUTOMATIC_CALLER is the only role here that no human may hold, and that
|
|
160
|
+
* fact is the ENTIRE safety argument for granting it this access: the
|
|
161
|
+
* reachability prober needs the same candidate pool an agent sees, and the
|
|
162
|
+
* seat is safe to give it to only because the seat cannot be handed out.
|
|
163
|
+
*
|
|
164
|
+
* That argument rests on the role being absent from UserRoleSchema — the
|
|
165
|
+
* assignable list the users API validates create/update against — and
|
|
166
|
+
* nothing asserted it. A future "publish all the roles" refactor would
|
|
167
|
+
* otherwise hand shared-curated-match access to a role a human CAN be
|
|
168
|
+
* assigned, with a green suite. Same assumption, same test, for the three
|
|
169
|
+
* older service roles, which carry more authority still.
|
|
170
|
+
*/
|
|
171
|
+
it.each(['AUTOMATIC_CALLER', 'BOT', 'CRON_SCHEDULER', 'OUTREACH_SERVICE'])('keeps the %s service role out of the assignable role list', (serviceRole) => {
|
|
172
|
+
expect(users_contract_1.UserRoleSchema.options).not.toContain(serviceRole);
|
|
173
|
+
});
|
|
174
|
+
it('never grants shared curated match access to an assignable role by accident', () => {
|
|
175
|
+
// The positive cases above are deliberate. This one guards the inverse:
|
|
176
|
+
// every assignable role that passes must be one someone chose, so adding
|
|
177
|
+
// a role to UserRoleSchema can never quietly widen the predicate.
|
|
178
|
+
const assignableWithAccess = users_contract_1.UserRoleSchema.options.filter((role) => (0, abilities_contract_1.hasSharedCuratedMatchAccess)([role]));
|
|
179
|
+
expect(assignableWithAccess.sort()).toEqual(['ADMIN', 'WORKER_CURATOR']);
|
|
180
|
+
});
|
|
140
181
|
it('grants only the purpose-limited workspace, not curated internals', () => {
|
|
141
182
|
expect(abilities_contract_1.InterconnectionAbilities).toEqual(expect.arrayContaining([
|
|
142
183
|
{ action: 'read', subject: 'CuratedMatchWorkspace' },
|
|
@@ -166,9 +207,28 @@ describe('shared curated match access', () => {
|
|
|
166
207
|
},
|
|
167
208
|
]);
|
|
168
209
|
});
|
|
169
|
-
it('grants SECOND_AGENT
|
|
170
|
-
|
|
171
|
-
|
|
210
|
+
it('grants SECOND_AGENT an update on CuratedWorker restricted to exactly the AI-appliable profile fields', () => {
|
|
211
|
+
// Scoped to power CandidateCallProfileFactsService's automatic write path
|
|
212
|
+
// (apps/api/src/modules/candidate-calling/services/candidate-call-profile-facts.service.ts,
|
|
213
|
+
// the `AppliableField` union, which gained `nationality` 2026-08-21 —
|
|
214
|
+
// see NATIONALITY_AUTO_APPLY_CONFIDENCE) — SECOND_AGENT still has no
|
|
215
|
+
// unconditioned `update CuratedWorker` the way WORKER_CURATOR does.
|
|
216
|
+
const curatedWorkerRules = abilities_contract_1.SecondAgentAbilities.filter((rule) => rule.subject === 'CuratedWorker');
|
|
217
|
+
expect(curatedWorkerRules).toEqual([
|
|
218
|
+
{
|
|
219
|
+
action: 'update',
|
|
220
|
+
subject: 'CuratedWorker',
|
|
221
|
+
fields: [
|
|
222
|
+
'postcode',
|
|
223
|
+
'transportMethods',
|
|
224
|
+
'englishLevel',
|
|
225
|
+
'hasTools',
|
|
226
|
+
'hasPpe',
|
|
227
|
+
'trades',
|
|
228
|
+
'nationality',
|
|
229
|
+
],
|
|
230
|
+
},
|
|
231
|
+
]);
|
|
172
232
|
});
|
|
173
233
|
});
|
|
174
234
|
describe('isCandidateOnlyCuratedViewer', () => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[]
|
|
@@ -788,6 +788,20 @@
|
|
|
788
788
|
"agentId": "{{ id }}"
|
|
789
789
|
}
|
|
790
790
|
},
|
|
791
|
+
{
|
|
792
|
+
"action": "read",
|
|
793
|
+
"subject": "LeadCallback",
|
|
794
|
+
"conditions": {
|
|
795
|
+
"agentId": "{{ id }}"
|
|
796
|
+
}
|
|
797
|
+
},
|
|
798
|
+
{
|
|
799
|
+
"action": "update",
|
|
800
|
+
"subject": "LeadCallback",
|
|
801
|
+
"conditions": {
|
|
802
|
+
"agentId": "{{ id }}"
|
|
803
|
+
}
|
|
804
|
+
},
|
|
791
805
|
{
|
|
792
806
|
"action": "read",
|
|
793
807
|
"subject": "CallHistory",
|
|
@@ -34,6 +34,8 @@
|
|
|
34
34
|
"job",
|
|
35
35
|
"job.*",
|
|
36
36
|
"channel",
|
|
37
|
+
"direction",
|
|
38
|
+
"durationSeconds",
|
|
37
39
|
"contactedAt",
|
|
38
40
|
"outcome",
|
|
39
41
|
"feedbackAt",
|
|
@@ -46,6 +48,11 @@
|
|
|
46
48
|
"jobResult",
|
|
47
49
|
"jobResult.*",
|
|
48
50
|
"canRecordFeedback",
|
|
51
|
+
"managedCallId",
|
|
52
|
+
"managedFeedbackStatus",
|
|
53
|
+
"managedCallStatus",
|
|
54
|
+
"managedHasRecording",
|
|
55
|
+
"managedCallSource",
|
|
49
56
|
"worker.name.value",
|
|
50
57
|
"worker.name.exact",
|
|
51
58
|
"worker.phone",
|
|
@@ -76,6 +83,15 @@
|
|
|
76
83
|
{
|
|
77
84
|
"action": "read",
|
|
78
85
|
"subject": "FilterCandidateContactHistorySchema",
|
|
79
|
-
"fields": [
|
|
86
|
+
"fields": [
|
|
87
|
+
"worker",
|
|
88
|
+
"worker.*",
|
|
89
|
+
"worker.name.*",
|
|
90
|
+
"job",
|
|
91
|
+
"job.*",
|
|
92
|
+
"job.location.*",
|
|
93
|
+
"status",
|
|
94
|
+
"channel"
|
|
95
|
+
]
|
|
80
96
|
}
|
|
81
97
|
]
|
|
@@ -125,6 +125,8 @@
|
|
|
125
125
|
"longitude",
|
|
126
126
|
"postcode",
|
|
127
127
|
"filledPositions",
|
|
128
|
+
"callPriority",
|
|
129
|
+
"callPriority.*",
|
|
128
130
|
"pay",
|
|
129
131
|
"pay.isNegotiable",
|
|
130
132
|
"pay.rate",
|
|
@@ -692,6 +694,8 @@
|
|
|
692
694
|
"job",
|
|
693
695
|
"job.*",
|
|
694
696
|
"channel",
|
|
697
|
+
"direction",
|
|
698
|
+
"durationSeconds",
|
|
695
699
|
"contactedAt",
|
|
696
700
|
"outcome",
|
|
697
701
|
"feedbackAt",
|
|
@@ -704,6 +708,11 @@
|
|
|
704
708
|
"jobResult",
|
|
705
709
|
"jobResult.*",
|
|
706
710
|
"canRecordFeedback",
|
|
711
|
+
"managedCallId",
|
|
712
|
+
"managedFeedbackStatus",
|
|
713
|
+
"managedCallStatus",
|
|
714
|
+
"managedHasRecording",
|
|
715
|
+
"managedCallSource",
|
|
707
716
|
"worker.name.value",
|
|
708
717
|
"worker.name.exact",
|
|
709
718
|
"worker.phone",
|
|
@@ -734,6 +743,44 @@
|
|
|
734
743
|
{
|
|
735
744
|
"action": "read",
|
|
736
745
|
"subject": "FilterCandidateContactHistorySchema",
|
|
737
|
-
"fields": [
|
|
746
|
+
"fields": [
|
|
747
|
+
"worker",
|
|
748
|
+
"worker.*",
|
|
749
|
+
"worker.name.*",
|
|
750
|
+
"job",
|
|
751
|
+
"job.*",
|
|
752
|
+
"job.location.*",
|
|
753
|
+
"status",
|
|
754
|
+
"channel"
|
|
755
|
+
]
|
|
756
|
+
},
|
|
757
|
+
{
|
|
758
|
+
"action": "update",
|
|
759
|
+
"subject": "CuratedWorker",
|
|
760
|
+
"fields": [
|
|
761
|
+
"postcode",
|
|
762
|
+
"transportMethods",
|
|
763
|
+
"englishLevel",
|
|
764
|
+
"hasTools",
|
|
765
|
+
"hasPpe",
|
|
766
|
+
"trades",
|
|
767
|
+
"nationality"
|
|
768
|
+
]
|
|
769
|
+
},
|
|
770
|
+
{
|
|
771
|
+
"action": "read",
|
|
772
|
+
"subject": "CandidateCallingQueue"
|
|
773
|
+
},
|
|
774
|
+
{
|
|
775
|
+
"action": "create",
|
|
776
|
+
"subject": "CandidateCallingQueue"
|
|
777
|
+
},
|
|
778
|
+
{
|
|
779
|
+
"action": "update",
|
|
780
|
+
"subject": "CandidateCallingQueue"
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
"action": "delete",
|
|
784
|
+
"subject": "CandidateCallingQueue"
|
|
738
785
|
}
|
|
739
786
|
]
|
|
@@ -188,6 +188,8 @@
|
|
|
188
188
|
"job",
|
|
189
189
|
"job.*",
|
|
190
190
|
"channel",
|
|
191
|
+
"direction",
|
|
192
|
+
"durationSeconds",
|
|
191
193
|
"contactedAt",
|
|
192
194
|
"outcome",
|
|
193
195
|
"feedbackAt",
|
|
@@ -200,6 +202,11 @@
|
|
|
200
202
|
"jobResult",
|
|
201
203
|
"jobResult.*",
|
|
202
204
|
"canRecordFeedback",
|
|
205
|
+
"managedCallId",
|
|
206
|
+
"managedFeedbackStatus",
|
|
207
|
+
"managedCallStatus",
|
|
208
|
+
"managedHasRecording",
|
|
209
|
+
"managedCallSource",
|
|
203
210
|
"worker.name.value",
|
|
204
211
|
"worker.name.exact",
|
|
205
212
|
"worker.phone",
|
|
@@ -230,6 +237,15 @@
|
|
|
230
237
|
{
|
|
231
238
|
"action": "read",
|
|
232
239
|
"subject": "FilterCandidateContactHistorySchema",
|
|
233
|
-
"fields": [
|
|
240
|
+
"fields": [
|
|
241
|
+
"worker",
|
|
242
|
+
"worker.*",
|
|
243
|
+
"worker.name.*",
|
|
244
|
+
"job",
|
|
245
|
+
"job.*",
|
|
246
|
+
"job.location.*",
|
|
247
|
+
"status",
|
|
248
|
+
"channel"
|
|
249
|
+
]
|
|
234
250
|
}
|
|
235
251
|
]
|