@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.
Files changed (139) hide show
  1. package/dist/abilities/abilities.contract.d.ts +28 -1
  2. package/dist/abilities/abilities.contract.d.ts.map +1 -1
  3. package/dist/abilities/abilities.contract.js +32 -1
  4. package/dist/abilities/abilities.contract.spec.js +63 -3
  5. package/dist/abilities/admin-dashboard.abilities.test.js +1 -0
  6. package/dist/abilities/automatic-caller.abilities.json +1 -0
  7. package/dist/abilities/first-agent.abilities.json +14 -0
  8. package/dist/abilities/interconnection.abilities.json +17 -1
  9. package/dist/abilities/office-manager.abilities.json +4 -0
  10. package/dist/abilities/second-agent.abilities.json +48 -1
  11. package/dist/abilities/worker-curator.abilities.json +17 -1
  12. package/dist/actives/actives.contract.d.ts +6959 -6547
  13. package/dist/actives/actives.contract.d.ts.map +1 -1
  14. package/dist/agent-client-links/agent-client-links.contract.d.ts +1275 -1173
  15. package/dist/agent-client-links/agent-client-links.contract.d.ts.map +1 -1
  16. package/dist/auth/auth.contract.d.ts +102 -102
  17. package/dist/bookings/backdate-guard.spec.js +24 -32
  18. package/dist/bookings/bookings.contract.d.ts +9963 -9305
  19. package/dist/bookings/bookings.contract.d.ts.map +1 -1
  20. package/dist/bookings/bookings.contract.js +2 -16
  21. package/dist/call-history/call-history.contract.d.ts +1040 -828
  22. package/dist/call-history/call-history.contract.d.ts.map +1 -1
  23. package/dist/calls-feed/calls-feed.contract.d.ts +138 -98
  24. package/dist/calls-feed/calls-feed.contract.d.ts.map +1 -1
  25. package/dist/candidate-calling/candidate-calling.contract.d.ts +18372 -0
  26. package/dist/candidate-calling/candidate-calling.contract.d.ts.map +1 -0
  27. package/dist/candidate-calling/candidate-calling.contract.js +494 -0
  28. package/dist/candidate-calling/candidate-calling.contract.spec.d.ts +2 -0
  29. package/dist/candidate-calling/candidate-calling.contract.spec.d.ts.map +1 -0
  30. package/dist/candidate-calling/candidate-calling.contract.spec.js +357 -0
  31. package/dist/candidate-calling/candidate-dialpad-call.schemas.d.ts +10 -0
  32. package/dist/candidate-calling/candidate-dialpad-call.schemas.d.ts.map +1 -0
  33. package/dist/candidate-calling/candidate-dialpad-call.schemas.js +33 -0
  34. package/dist/client-contacts/client-contacts.contract.d.ts +622 -622
  35. package/dist/clients/clients.contract.d.ts +289 -289
  36. package/dist/collaboration-checkings/collaboration-checkings.contract.d.ts +3108 -3004
  37. package/dist/collaboration-checkings/collaboration-checkings.contract.d.ts.map +1 -1
  38. package/dist/collaborations/collaborations.contract.d.ts +2604 -2507
  39. package/dist/collaborations/collaborations.contract.d.ts.map +1 -1
  40. package/dist/common/callback-slots.d.ts +4 -0
  41. package/dist/common/callback-slots.d.ts.map +1 -0
  42. package/dist/common/callback-slots.js +20 -0
  43. package/dist/common/common-schemas.d.ts +10 -4
  44. package/dist/common/common-schemas.d.ts.map +1 -1
  45. package/dist/common/common-schemas.js +6 -0
  46. package/dist/companies/companies.contract.d.ts +120 -120
  47. package/dist/crews/crews.contract.d.ts +278 -278
  48. package/dist/cron-executions/cron-executions.contract.d.ts +245 -245
  49. package/dist/cron-executions/cron-executions.contract.d.ts.map +1 -1
  50. package/dist/cron-executions/cron-executions.contract.js +1 -0
  51. package/dist/curated-worker-leads/candidate-coordination.contract.d.ts +3830 -2354
  52. package/dist/curated-worker-leads/candidate-coordination.contract.d.ts.map +1 -1
  53. package/dist/curated-worker-leads/candidate-coordination.contract.js +73 -7
  54. package/dist/curated-worker-leads/candidate-edit-session.contract.d.ts +94 -94
  55. package/dist/curated-worker-leads/contact-history.spec.js +141 -0
  56. package/dist/curated-worker-leads/job-candidate-cards.spec.js +19 -0
  57. package/dist/curated-worker-leads/job-candidates.spec.js +179 -0
  58. package/dist/curated-worker-leads/jobs-tab.contract.d.ts +8185 -2106
  59. package/dist/curated-worker-leads/jobs-tab.contract.d.ts.map +1 -1
  60. package/dist/curated-worker-leads/jobs-tab.contract.js +126 -1
  61. package/dist/curated-worker-leads/owned-jobs-tab.contract.d.ts +110 -110
  62. package/dist/curated-workers/curated-workers.contract.d.ts +2033 -1951
  63. package/dist/curated-workers/curated-workers.contract.d.ts.map +1 -1
  64. package/dist/dashboards/dashboard-widgets.contact-history.spec.d.ts +2 -0
  65. package/dist/dashboards/dashboard-widgets.contact-history.spec.d.ts.map +1 -0
  66. package/dist/dashboards/dashboard-widgets.contact-history.spec.js +160 -0
  67. package/dist/dashboards/dashboard-widgets.contract.d.ts +1027 -284
  68. package/dist/dashboards/dashboard-widgets.contract.d.ts.map +1 -1
  69. package/dist/dashboards/dashboard-widgets.contract.js +46 -1
  70. package/dist/dashboards/dashboard.contract.d.ts +8 -8
  71. package/dist/document-intake/document-intake.contract.d.ts +1145 -1145
  72. package/dist/export-jobs/export-jobs.contract.d.ts +755 -755
  73. package/dist/exports-events/exports-events.schemas.d.ts +6 -6
  74. package/dist/index.d.ts +5 -0
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +5 -0
  77. package/dist/jobs/jobs.contract.d.ts +8507 -6044
  78. package/dist/jobs/jobs.contract.d.ts.map +1 -1
  79. package/dist/jobs/jobs.contract.js +95 -2
  80. package/dist/jobs/jobs.contract.spec.js +231 -1
  81. package/dist/kpi-impersonation/kpi-impersonation.contract.d.ts +102 -102
  82. package/dist/lead-assignments/lead-assignments.contract.d.ts +2985 -1139
  83. package/dist/lead-assignments/lead-assignments.contract.d.ts.map +1 -1
  84. package/dist/lead-assignments/lead-assignments.contract.js +102 -2
  85. package/dist/lead-assignments/lead-assignments.contract.spec.d.ts +2 -0
  86. package/dist/lead-assignments/lead-assignments.contract.spec.d.ts.map +1 -0
  87. package/dist/lead-assignments/lead-assignments.contract.spec.js +51 -0
  88. package/dist/lead-distribution/agent-lead-distribution.contract.d.ts +341 -317
  89. package/dist/lead-distribution/agent-lead-distribution.contract.d.ts.map +1 -1
  90. package/dist/leads/leads.contract.d.ts +282 -282
  91. package/dist/locations/location-enrichment.contract.spec.d.ts +2 -0
  92. package/dist/locations/location-enrichment.contract.spec.d.ts.map +1 -0
  93. package/dist/locations/location-enrichment.contract.spec.js +50 -0
  94. package/dist/locations/locations.contract.d.ts +132 -98
  95. package/dist/locations/locations.contract.d.ts.map +1 -1
  96. package/dist/locations/locations.contract.js +10 -0
  97. package/dist/notifications/notifications.contract.d.ts +579 -107
  98. package/dist/notifications/notifications.contract.d.ts.map +1 -1
  99. package/dist/notifications/notifications.contract.js +36 -2
  100. package/dist/notifications/notifications.contract.spec.d.ts +2 -0
  101. package/dist/notifications/notifications.contract.spec.d.ts.map +1 -0
  102. package/dist/notifications/notifications.contract.spec.js +39 -0
  103. package/dist/outreach/__tests__/outreach-claim.test.js +33 -0
  104. package/dist/outreach/__tests__/outreach-routes.test.js +8 -0
  105. package/dist/outreach/outreach.contract.d.ts +583 -162
  106. package/dist/outreach/outreach.contract.d.ts.map +1 -1
  107. package/dist/outreach/outreach.contract.js +50 -1
  108. package/dist/outreach/relay-hub-outreach.contract.d.ts +299 -121
  109. package/dist/outreach/relay-hub-outreach.contract.d.ts.map +1 -1
  110. package/dist/outreach/relay-hub-outreach.contract.js +10 -0
  111. package/dist/outreach/relay-hub-outreach.contract.spec.js +26 -0
  112. package/dist/outreach/relay-hub-outreach.schemas.d.ts +94 -0
  113. package/dist/outreach/relay-hub-outreach.schemas.d.ts.map +1 -0
  114. package/dist/outreach/relay-hub-outreach.schemas.js +15 -0
  115. package/dist/own-research/check-phone-response.spec.d.ts +2 -0
  116. package/dist/own-research/check-phone-response.spec.d.ts.map +1 -0
  117. package/dist/own-research/check-phone-response.spec.js +54 -0
  118. package/dist/own-research/own-research.contract.d.ts +971 -820
  119. package/dist/own-research/own-research.contract.d.ts.map +1 -1
  120. package/dist/own-research/own-research.contract.js +6 -1
  121. package/dist/proofs/proofs.contract.d.ts +356 -356
  122. package/dist/proofs/proofs.dtos.d.ts +148 -148
  123. package/dist/realtime/job-call-priority-updated.d.ts +18 -0
  124. package/dist/realtime/job-call-priority-updated.d.ts.map +1 -0
  125. package/dist/realtime/job-call-priority-updated.js +17 -0
  126. package/dist/shared/summary-schemas.d.ts +36 -27
  127. package/dist/shared/summary-schemas.d.ts.map +1 -1
  128. package/dist/shared/summary-schemas.js +7 -0
  129. package/dist/sheets-sync/sheets-sync.contract.d.ts +683 -683
  130. package/dist/user-access-grants/user-access-grants.contract.d.ts +216 -216
  131. package/dist/users/users.contract.d.ts +365 -336
  132. package/dist/users/users.contract.d.ts.map +1 -1
  133. package/dist/users/users.contract.js +9 -1
  134. package/dist/users/users.contract.spec.js +39 -0
  135. package/dist/worker-source-identity-conflicts/worker-source-identity-conflicts.contract.d.ts +150 -150
  136. package/dist/workers/workers.contract.d.ts +4505 -4261
  137. package/dist/workers/workers.contract.d.ts.map +1 -1
  138. package/dist/workers/workers.contract.js +12 -0
  139. 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;AAcH,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,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;;;;;;;;;;;;;CAahB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,OAAO,aAAa,CAAC;AAErD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,8uBAkCnB,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,eAAO,MAAM,0BAA0B,yDAIC,CAAC;AAWzC,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAQT;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"}
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 no CuratedWorker rule', () => {
170
- const subjects = abilities_contract_1.SecondAgentAbilities.map((rule) => rule.subject);
171
- expect(subjects).not.toContain('CuratedWorker');
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', () => {
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const abilities_contract_1 = require("./abilities.contract");
4
4
  const subjects = [
5
+ 'AdminSharedDashboardWidgets',
5
6
  'AdminFaDashboardWidgets',
6
7
  'AdminSaDashboardWidgets',
7
8
  'AdminAgentStats',
@@ -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": ["worker", "worker.*", "job", "job.*", "status", "channel"]
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
  ]
@@ -47,6 +47,10 @@
47
47
  "officeId": { "$in": "{{ managedOfficeIds }}" }
48
48
  }
49
49
  },
50
+ {
51
+ "action": "read",
52
+ "subject": "AdminSharedDashboardWidgets"
53
+ },
50
54
  {
51
55
  "action": "read",
52
56
  "subject": "AdminFaDashboardWidgets"
@@ -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": ["worker", "worker.*", "job", "job.*", "status", "channel"]
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": ["worker", "worker.*", "job", "job.*", "status", "channel"]
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
  ]