@dakkitor/api-contracts 1.9.1 → 1.9.3

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 (111) 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 +31 -1
  4. package/dist/abilities/abilities.contract.spec.js +52 -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 +32 -1
  11. package/dist/abilities/worker-curator.abilities.json +17 -1
  12. package/dist/actives/actives.contract.d.ts +7200 -6919
  13. package/dist/actives/actives.contract.d.ts.map +1 -1
  14. package/dist/agent-client-links/agent-client-links.contract.d.ts +137 -137
  15. package/dist/auth/auth.contract.d.ts +85 -85
  16. package/dist/bookings/backdate-guard.spec.js +24 -32
  17. package/dist/bookings/bookings.contract.d.ts +10542 -10116
  18. package/dist/bookings/bookings.contract.d.ts.map +1 -1
  19. package/dist/bookings/bookings.contract.js +2 -16
  20. package/dist/call-history/call-history.contract.d.ts +315 -140
  21. package/dist/call-history/call-history.contract.d.ts.map +1 -1
  22. package/dist/calls-feed/calls-feed.contract.d.ts +39 -6
  23. package/dist/calls-feed/calls-feed.contract.d.ts.map +1 -1
  24. package/dist/candidate-calling/candidate-calling.contract.d.ts +9230 -4114
  25. package/dist/candidate-calling/candidate-calling.contract.d.ts.map +1 -1
  26. package/dist/candidate-calling/candidate-calling.contract.js +362 -16
  27. package/dist/candidate-calling/candidate-calling.contract.spec.js +164 -0
  28. package/dist/candidate-calling/candidate-dialpad-call.schemas.d.ts +10 -0
  29. package/dist/candidate-calling/candidate-dialpad-call.schemas.d.ts.map +1 -0
  30. package/dist/candidate-calling/candidate-dialpad-call.schemas.js +33 -0
  31. package/dist/client-contacts/client-contacts.contract.d.ts +622 -622
  32. package/dist/clients/clients.contract.d.ts +289 -289
  33. package/dist/collaboration-checkings/collaboration-checkings.contract.d.ts +601 -601
  34. package/dist/collaborations/collaborations.contract.d.ts +538 -538
  35. package/dist/common/callback-slots.d.ts +4 -0
  36. package/dist/common/callback-slots.d.ts.map +1 -0
  37. package/dist/common/callback-slots.js +20 -0
  38. package/dist/common/common-schemas.d.ts +10 -4
  39. package/dist/common/common-schemas.d.ts.map +1 -1
  40. package/dist/common/common-schemas.js +6 -0
  41. package/dist/companies/companies.contract.d.ts +120 -120
  42. package/dist/crews/crews.contract.d.ts +278 -278
  43. package/dist/cron-executions/cron-executions.contract.d.ts +238 -238
  44. package/dist/curated-worker-leads/candidate-coordination.contract.d.ts +2154 -1296
  45. package/dist/curated-worker-leads/candidate-coordination.contract.d.ts.map +1 -1
  46. package/dist/curated-worker-leads/candidate-coordination.contract.js +36 -3
  47. package/dist/curated-worker-leads/candidate-edit-session.contract.d.ts +300 -300
  48. package/dist/curated-worker-leads/contact-history.spec.js +86 -0
  49. package/dist/curated-worker-leads/job-candidate-cards.spec.js +19 -0
  50. package/dist/curated-worker-leads/job-candidates.spec.js +179 -0
  51. package/dist/curated-worker-leads/jobs-tab.contract.d.ts +8598 -2519
  52. package/dist/curated-worker-leads/jobs-tab.contract.d.ts.map +1 -1
  53. package/dist/curated-worker-leads/jobs-tab.contract.js +126 -1
  54. package/dist/curated-worker-leads/owned-jobs-tab.contract.d.ts +110 -110
  55. package/dist/curated-workers/curated-workers.contract.d.ts +1213 -1131
  56. package/dist/curated-workers/curated-workers.contract.d.ts.map +1 -1
  57. package/dist/dashboards/dashboard-widgets.contact-history.spec.d.ts +2 -0
  58. package/dist/dashboards/dashboard-widgets.contact-history.spec.d.ts.map +1 -0
  59. package/dist/dashboards/dashboard-widgets.contact-history.spec.js +160 -0
  60. package/dist/dashboards/dashboard-widgets.contract.d.ts +1278 -535
  61. package/dist/dashboards/dashboard-widgets.contract.d.ts.map +1 -1
  62. package/dist/dashboards/dashboard-widgets.contract.js +46 -1
  63. package/dist/dashboards/dashboard.contract.d.ts +8 -8
  64. package/dist/document-intake/document-intake.contract.d.ts +1145 -1145
  65. package/dist/export-jobs/export-jobs.contract.d.ts +663 -663
  66. package/dist/exports-events/exports-events.schemas.d.ts +2 -2
  67. package/dist/index.d.ts +1 -0
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +1 -0
  70. package/dist/jobs/jobs.contract.d.ts +5586 -3381
  71. package/dist/jobs/jobs.contract.d.ts.map +1 -1
  72. package/dist/jobs/jobs.contract.js +95 -2
  73. package/dist/jobs/jobs.contract.spec.js +231 -1
  74. package/dist/kpi-impersonation/kpi-impersonation.contract.d.ts +123 -123
  75. package/dist/lead-assignments/lead-assignments.contract.d.ts +1897 -122
  76. package/dist/lead-assignments/lead-assignments.contract.d.ts.map +1 -1
  77. package/dist/lead-assignments/lead-assignments.contract.js +102 -2
  78. package/dist/lead-assignments/lead-assignments.contract.spec.d.ts +2 -0
  79. package/dist/lead-assignments/lead-assignments.contract.spec.d.ts.map +1 -0
  80. package/dist/lead-assignments/lead-assignments.contract.spec.js +51 -0
  81. package/dist/lead-distribution/agent-lead-distribution.contract.d.ts +103 -103
  82. package/dist/leads/leads.contract.d.ts +210 -210
  83. package/dist/locations/location-enrichment.contract.spec.d.ts +2 -0
  84. package/dist/locations/location-enrichment.contract.spec.d.ts.map +1 -0
  85. package/dist/locations/location-enrichment.contract.spec.js +50 -0
  86. package/dist/locations/locations.contract.d.ts +132 -98
  87. package/dist/locations/locations.contract.d.ts.map +1 -1
  88. package/dist/locations/locations.contract.js +10 -0
  89. package/dist/notifications/notifications.contract.d.ts +512 -40
  90. package/dist/notifications/notifications.contract.d.ts.map +1 -1
  91. package/dist/notifications/notifications.contract.js +36 -2
  92. package/dist/notifications/notifications.contract.spec.d.ts +2 -0
  93. package/dist/notifications/notifications.contract.spec.d.ts.map +1 -0
  94. package/dist/notifications/notifications.contract.spec.js +39 -0
  95. package/dist/own-research/own-research.contract.d.ts +196 -130
  96. package/dist/own-research/own-research.contract.d.ts.map +1 -1
  97. package/dist/proofs/proofs.contract.d.ts +356 -356
  98. package/dist/proofs/proofs.dtos.d.ts +148 -148
  99. package/dist/realtime/job-call-priority-updated.d.ts +18 -0
  100. package/dist/realtime/job-call-priority-updated.d.ts.map +1 -0
  101. package/dist/realtime/job-call-priority-updated.js +17 -0
  102. package/dist/shared/summary-schemas.d.ts +36 -27
  103. package/dist/shared/summary-schemas.d.ts.map +1 -1
  104. package/dist/shared/summary-schemas.js +7 -0
  105. package/dist/sheets-sync/sheets-sync.contract.d.ts +683 -683
  106. package/dist/user-access-grants/user-access-grants.contract.d.ts +55 -55
  107. package/dist/users/users.contract.d.ts +236 -236
  108. package/dist/worker-source-identity-conflicts/worker-source-identity-conflicts.contract.d.ts +69 -69
  109. package/dist/workers/workers.contract.d.ts +2620 -2420
  110. package/dist/workers/workers.contract.d.ts.map +1 -1
  111. 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", "CandidateCallingQueue", "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,uwBAmCnB,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',
@@ -118,6 +122,14 @@ function getRolesOmCannotAssign(actingUserRoles) {
118
122
  const allowed = new Set(exports.OFFICE_MANAGER_ASSIGNABLE_ROLES);
119
123
  return users_contract_1.UserRoleSchema.options.filter((role) => !allowed.has(role));
120
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
+ */
121
133
  exports.SHARED_CURATED_MATCH_ROLES = [
122
134
  'ADMIN',
123
135
  'WORKER_CURATOR',
@@ -127,11 +139,29 @@ function hasInterconnectionModifierPair(roles) {
127
139
  return (roles?.includes('SECOND_AGENT') === true &&
128
140
  roles.includes('INTERCONNECTION'));
129
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
+ */
130
159
  function hasSharedCuratedMatchAccess(roles) {
131
160
  if (!roles)
132
161
  return false;
133
162
  return (roles.includes('ADMIN') ||
134
163
  roles.includes('WORKER_CURATOR') ||
164
+ roles.includes('AUTOMATIC_CALLER') ||
135
165
  hasInterconnectionModifierPair(roles));
136
166
  }
137
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',
@@ -105,6 +107,10 @@ describe('candidate calling queue grants', () => {
105
107
  { action: 'delete', subject: 'CandidateCallingQueue' },
106
108
  ]);
107
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
+ });
108
114
  });
109
115
  describe('Relay pod membership grants', () => {
110
116
  it('grants no RelayPod authority; pod access comes from membership', () => {
@@ -144,10 +150,34 @@ describe('shared curated match access', () => {
144
150
  [['FIRST_AGENT', 'INTERCONNECTION'], false],
145
151
  [['SECOND_AGENT'], false],
146
152
  [['FIRST_AGENT'], false],
153
+ [['AUTOMATIC_CALLER'], true],
147
154
  [[], false],
148
155
  ])('%j => %s', (roles, expected) => {
149
156
  expect((0, abilities_contract_1.hasSharedCuratedMatchAccess)(roles)).toBe(expected);
150
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
+ });
151
181
  it('grants only the purpose-limited workspace, not curated internals', () => {
152
182
  expect(abilities_contract_1.InterconnectionAbilities).toEqual(expect.arrayContaining([
153
183
  { action: 'read', subject: 'CuratedMatchWorkspace' },
@@ -177,9 +207,28 @@ describe('shared curated match access', () => {
177
207
  },
178
208
  ]);
179
209
  });
180
- it('grants SECOND_AGENT no CuratedWorker rule', () => {
181
- const subjects = abilities_contract_1.SecondAgentAbilities.map((rule) => rule.subject);
182
- 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
+ ]);
183
232
  });
184
233
  });
185
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,7 +743,29 @@
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
+ ]
738
769
  },
739
770
  {
740
771
  "action": "read",
@@ -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
  ]