@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.
- 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 +31 -1
- package/dist/abilities/abilities.contract.spec.js +52 -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 +32 -1
- package/dist/abilities/worker-curator.abilities.json +17 -1
- package/dist/actives/actives.contract.d.ts +7200 -6919
- package/dist/actives/actives.contract.d.ts.map +1 -1
- package/dist/agent-client-links/agent-client-links.contract.d.ts +137 -137
- package/dist/auth/auth.contract.d.ts +85 -85
- package/dist/bookings/backdate-guard.spec.js +24 -32
- package/dist/bookings/bookings.contract.d.ts +10542 -10116
- 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 +315 -140
- package/dist/call-history/call-history.contract.d.ts.map +1 -1
- package/dist/calls-feed/calls-feed.contract.d.ts +39 -6
- package/dist/calls-feed/calls-feed.contract.d.ts.map +1 -1
- package/dist/candidate-calling/candidate-calling.contract.d.ts +9230 -4114
- package/dist/candidate-calling/candidate-calling.contract.d.ts.map +1 -1
- package/dist/candidate-calling/candidate-calling.contract.js +362 -16
- package/dist/candidate-calling/candidate-calling.contract.spec.js +164 -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 +601 -601
- package/dist/collaborations/collaborations.contract.d.ts +538 -538
- 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 +238 -238
- package/dist/curated-worker-leads/candidate-coordination.contract.d.ts +2154 -1296
- package/dist/curated-worker-leads/candidate-coordination.contract.d.ts.map +1 -1
- package/dist/curated-worker-leads/candidate-coordination.contract.js +36 -3
- package/dist/curated-worker-leads/candidate-edit-session.contract.d.ts +300 -300
- package/dist/curated-worker-leads/contact-history.spec.js +86 -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 +8598 -2519
- 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 +1213 -1131
- 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 +1278 -535
- 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 +663 -663
- package/dist/exports-events/exports-events.schemas.d.ts +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/jobs/jobs.contract.d.ts +5586 -3381
- 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 +123 -123
- package/dist/lead-assignments/lead-assignments.contract.d.ts +1897 -122
- 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 +103 -103
- package/dist/leads/leads.contract.d.ts +210 -210
- 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 +512 -40
- 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/own-research/own-research.contract.d.ts +196 -130
- package/dist/own-research/own-research.contract.d.ts.map +1 -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 +55 -55
- package/dist/users/users.contract.d.ts +236 -236
- package/dist/worker-source-identity-conflicts/worker-source-identity-conflicts.contract.d.ts +69 -69
- package/dist/workers/workers.contract.d.ts +2620 -2420
- package/dist/workers/workers.contract.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -5,6 +5,13 @@ const ID = '7d5c0f4e-8f60-4bff-b544-000000000001';
|
|
|
5
5
|
const JOB_ID = '7d5c0f4e-8f60-4bff-b544-000000000002';
|
|
6
6
|
const SUBJECT_ID = '7d5c0f4e-8f60-4bff-b544-000000000003';
|
|
7
7
|
describe('candidate contact history contract', () => {
|
|
8
|
+
it('rejects an impossible NOT_LOOKING return date', () => {
|
|
9
|
+
expect(candidate_coordination_contract_1.ContactWorkerStateSchema.safeParse({
|
|
10
|
+
kind: 'NOT_LOOKING',
|
|
11
|
+
days: 30,
|
|
12
|
+
returnDate: '2026-02-31',
|
|
13
|
+
}).success).toBe(false);
|
|
14
|
+
});
|
|
8
15
|
it('parses structured worker and job filters', () => {
|
|
9
16
|
expect(candidate_coordination_contract_1.CandidateContactHistoryQuerySchema.parse({
|
|
10
17
|
contactedById: ID,
|
|
@@ -62,6 +69,8 @@ describe('candidate contact history contract', () => {
|
|
|
62
69
|
},
|
|
63
70
|
},
|
|
64
71
|
channel: 'WHATSAPP',
|
|
72
|
+
direction: 'OUTBOUND',
|
|
73
|
+
durationSeconds: null,
|
|
65
74
|
contactedAt: '2026-07-17T09:00:00.000Z',
|
|
66
75
|
outcome: 'AWAITING_FEEDBACK',
|
|
67
76
|
feedbackAt: null,
|
|
@@ -85,6 +94,47 @@ describe('candidate contact history contract', () => {
|
|
|
85
94
|
expect(candidate_coordination_contract_1.candidateCoordinationContract.contactHistory.method).toBe('GET');
|
|
86
95
|
expect(candidate_coordination_contract_1.candidateCoordinationContract.recordWhatsAppFeedback.method).toBe('POST');
|
|
87
96
|
expect(candidate_coordination_contract_1.candidateCoordinationContract.recordContactFeedback.path).toBe('/v2/candidate-contacts/:contactEventId/feedback');
|
|
97
|
+
expect(candidate_coordination_contract_1.CompletePhoneCallBodySchema.safeParse({
|
|
98
|
+
outcome: 'FAILED',
|
|
99
|
+
scope: 'THIS_JOB',
|
|
100
|
+
reason: 'DISTANCE',
|
|
101
|
+
}).success).toBe(false);
|
|
102
|
+
expect(candidate_coordination_contract_1.ContactConnectionResultSchema.safeParse('FAILED').success).toBe(false);
|
|
103
|
+
});
|
|
104
|
+
it('parses job-agnostic Dialpad history outcomes with call metadata', () => {
|
|
105
|
+
const baseItem = {
|
|
106
|
+
id: ID,
|
|
107
|
+
agentId: ID,
|
|
108
|
+
subjectKind: 'CURATED',
|
|
109
|
+
subjectId: SUBJECT_ID,
|
|
110
|
+
viewerWorkerId: null,
|
|
111
|
+
worker: {
|
|
112
|
+
firstName: 'Jamie',
|
|
113
|
+
lastName: 'Taylor',
|
|
114
|
+
postcode: null,
|
|
115
|
+
},
|
|
116
|
+
channel: 'PHONE',
|
|
117
|
+
contactedAt: '2026-08-21T09:00:00.000Z',
|
|
118
|
+
feedbackAt: null,
|
|
119
|
+
feedback: null,
|
|
120
|
+
canRecordFeedback: false,
|
|
121
|
+
};
|
|
122
|
+
expect(candidate_coordination_contract_1.CandidateContactHistoryItemSchema.parse({
|
|
123
|
+
...baseItem,
|
|
124
|
+
job: null,
|
|
125
|
+
direction: 'INBOUND',
|
|
126
|
+
durationSeconds: 42,
|
|
127
|
+
outcome: 'CONNECTED',
|
|
128
|
+
connection: 'CONNECTED',
|
|
129
|
+
})).toMatchObject({ job: null, direction: 'INBOUND', outcome: 'CONNECTED' });
|
|
130
|
+
expect(candidate_coordination_contract_1.CandidateContactHistoryItemSchema.parse({
|
|
131
|
+
...baseItem,
|
|
132
|
+
job: null,
|
|
133
|
+
direction: 'OUTBOUND',
|
|
134
|
+
durationSeconds: null,
|
|
135
|
+
outcome: 'FAILED',
|
|
136
|
+
connection: 'FAILED',
|
|
137
|
+
})).toMatchObject({ direction: 'OUTBOUND', outcome: 'FAILED' });
|
|
88
138
|
});
|
|
89
139
|
it.each(['PROCESSING', 'NEEDS_REVIEW', 'FEEDBACK_RECORDED'])('projects managed %s status without private artifacts', (managedFeedbackStatus) => {
|
|
90
140
|
const response = {
|
|
@@ -107,6 +157,8 @@ describe('candidate contact history contract', () => {
|
|
|
107
157
|
firstAgent: null,
|
|
108
158
|
},
|
|
109
159
|
channel: 'PHONE',
|
|
160
|
+
direction: 'OUTBOUND',
|
|
161
|
+
durationSeconds: null,
|
|
110
162
|
contactedAt: '2026-08-19T12:00:00.000Z',
|
|
111
163
|
outcome: 'AWAITING_FEEDBACK',
|
|
112
164
|
feedbackAt: null,
|
|
@@ -141,4 +193,38 @@ describe('candidate contact history contract', () => {
|
|
|
141
193
|
recordingUrl: 'https://private.example.test/recording',
|
|
142
194
|
}).success).toBe(false);
|
|
143
195
|
});
|
|
196
|
+
it('projects managed call presentation fields without relaxing item strictness', () => {
|
|
197
|
+
const item = {
|
|
198
|
+
id: ID,
|
|
199
|
+
agentId: ID,
|
|
200
|
+
subjectKind: 'CURATED',
|
|
201
|
+
subjectId: SUBJECT_ID,
|
|
202
|
+
viewerWorkerId: null,
|
|
203
|
+
worker: {
|
|
204
|
+
firstName: 'Jamie',
|
|
205
|
+
lastName: 'Taylor',
|
|
206
|
+
postcode: null,
|
|
207
|
+
},
|
|
208
|
+
job: {
|
|
209
|
+
id: JOB_ID,
|
|
210
|
+
tradeName: null,
|
|
211
|
+
postcode: null,
|
|
212
|
+
firstAgent: null,
|
|
213
|
+
},
|
|
214
|
+
channel: 'PHONE',
|
|
215
|
+
direction: 'OUTBOUND',
|
|
216
|
+
durationSeconds: null,
|
|
217
|
+
contactedAt: '2026-08-19T12:00:00.000Z',
|
|
218
|
+
outcome: 'AWAITING_FEEDBACK',
|
|
219
|
+
feedbackAt: null,
|
|
220
|
+
feedback: null,
|
|
221
|
+
managedCallStatus: 'NEEDS_REVIEW',
|
|
222
|
+
managedHasRecording: true,
|
|
223
|
+
managedCallSource: 'HISTORICAL_IMPORT',
|
|
224
|
+
canRecordFeedback: true,
|
|
225
|
+
};
|
|
226
|
+
expect(candidate_coordination_contract_1.CandidateContactHistoryItemSchema.safeParse(item).success).toBe(true);
|
|
227
|
+
expect(candidate_coordination_contract_1.CandidateContactHistoryItemSchema.safeParse({ ...item, unknown: true })
|
|
228
|
+
.success).toBe(false);
|
|
229
|
+
});
|
|
144
230
|
});
|
|
@@ -67,6 +67,25 @@ describe('JobCandidateCardSchema / OwnedCandidateCardSchema', () => {
|
|
|
67
67
|
expect(parsed).not.toHaveProperty('email');
|
|
68
68
|
expect(parsed).not.toHaveProperty('nino');
|
|
69
69
|
});
|
|
70
|
+
it('keeps list ranking metadata out of the card hydration projection', () => {
|
|
71
|
+
const parsed = jobs_tab_contract_1.JobCandidateCardSchema.parse({
|
|
72
|
+
id: '7d5c0f4e-8f60-4bff-b544-111111111111',
|
|
73
|
+
firstName: 'Ana',
|
|
74
|
+
hasTools: true,
|
|
75
|
+
hasPpe: true,
|
|
76
|
+
offerOpenness: 'OPEN',
|
|
77
|
+
createdAt: new Date().toISOString(),
|
|
78
|
+
updatedAt: new Date().toISOString(),
|
|
79
|
+
qualifications: [],
|
|
80
|
+
hasPhoneNumber: true,
|
|
81
|
+
ranking: {
|
|
82
|
+
score: 84,
|
|
83
|
+
rank: 1,
|
|
84
|
+
reservationOwnerId: '6f8e5c4d-3b2a-4190-8c7d-6e5f4a3b2c1d',
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
expect(parsed).not.toHaveProperty('ranking');
|
|
88
|
+
});
|
|
70
89
|
it('strips sensitive keys nested inside curated candidate data', () => {
|
|
71
90
|
const parsed = jobs_tab_contract_1.JobCandidateCardSchema.parse({
|
|
72
91
|
id: '7d5c0f4e-8f60-4bff-b544-111111111111',
|
|
@@ -36,6 +36,12 @@ describe('JobCandidates schemas', () => {
|
|
|
36
36
|
qualifications: [],
|
|
37
37
|
hasPhoneNumber: true,
|
|
38
38
|
};
|
|
39
|
+
it('accepts only UUID candidate snapshot identities', () => {
|
|
40
|
+
const snapshotId = '00000000-0000-4000-8000-000000000001';
|
|
41
|
+
expect(jobs_tab_contract_1.jobsTabContract.candidates.query.parse({ page: 2, snapshotId })).toEqual({ page: 2, snapshotId });
|
|
42
|
+
expect(jobs_tab_contract_1.jobsTabContract.candidates.query.safeParse({ snapshotId: 'shared' })
|
|
43
|
+
.success).toBe(false);
|
|
44
|
+
});
|
|
39
45
|
it('parses a full row', () => {
|
|
40
46
|
expect(jobs_tab_contract_1.CandidateRowSchema.parse({
|
|
41
47
|
...row,
|
|
@@ -56,6 +62,163 @@ describe('JobCandidates schemas', () => {
|
|
|
56
62
|
},
|
|
57
63
|
});
|
|
58
64
|
});
|
|
65
|
+
it('parses an optional complete call-priority ranking', () => {
|
|
66
|
+
const parsed = jobs_tab_contract_1.CandidateRowSchema.parse({
|
|
67
|
+
...row,
|
|
68
|
+
ranking: {
|
|
69
|
+
score: 84,
|
|
70
|
+
rank: 1,
|
|
71
|
+
baseFit: 82,
|
|
72
|
+
continuityBoost: 14.3,
|
|
73
|
+
confidence: 'MEDIUM',
|
|
74
|
+
reasons: [
|
|
75
|
+
{ code: 'PRACTICAL_COMMUTE', routeMinutes: 14 },
|
|
76
|
+
{ code: 'QUALIFICATIONS_PARTIAL', matched: 2, required: 3 },
|
|
77
|
+
],
|
|
78
|
+
modelVersion: 'candidate-call-priority-v2',
|
|
79
|
+
computedAt: '2026-08-23T09:00:00.000Z',
|
|
80
|
+
decisionEvidence: {
|
|
81
|
+
proximity: {
|
|
82
|
+
score: 0.72,
|
|
83
|
+
routeMinutes: 14,
|
|
84
|
+
maxTravelMinutes: 50,
|
|
85
|
+
distanceKm: 5.2,
|
|
86
|
+
driveMinutes: 22,
|
|
87
|
+
transitMinutes: 48,
|
|
88
|
+
},
|
|
89
|
+
qualification: {
|
|
90
|
+
score: 0.8,
|
|
91
|
+
required: 3,
|
|
92
|
+
matched: 2,
|
|
93
|
+
explicit: true,
|
|
94
|
+
},
|
|
95
|
+
reliability: {
|
|
96
|
+
score: 0.76,
|
|
97
|
+
workerPositiveOutcomes: 6,
|
|
98
|
+
workerMatureOutcomes: 7,
|
|
99
|
+
tradePositiveOutcomes: 15,
|
|
100
|
+
tradeMatureOutcomes: 20,
|
|
101
|
+
globalPrior: 0.6,
|
|
102
|
+
},
|
|
103
|
+
readiness: {
|
|
104
|
+
score: 1,
|
|
105
|
+
state: 'CURRENT_OPEN',
|
|
106
|
+
offerOpenness: 'OPEN',
|
|
107
|
+
offerOpennessSetAt: '2026-08-22T09:00:00.000Z',
|
|
108
|
+
},
|
|
109
|
+
continuity: {
|
|
110
|
+
boost: 14.3,
|
|
111
|
+
outcome: 'CONNECTED',
|
|
112
|
+
acquiredAt: '2026-08-22T08:00:00.000Z',
|
|
113
|
+
expiresAt: '2026-08-24T08:00:00.000Z',
|
|
114
|
+
},
|
|
115
|
+
confidenceFlags: {
|
|
116
|
+
qualificationsExplicit: true,
|
|
117
|
+
matureReliability: true,
|
|
118
|
+
readinessCurrent: true,
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
expect(parsed.ranking).toEqual({
|
|
124
|
+
score: 84,
|
|
125
|
+
rank: 1,
|
|
126
|
+
baseFit: 82,
|
|
127
|
+
continuityBoost: 14.3,
|
|
128
|
+
confidence: 'MEDIUM',
|
|
129
|
+
reasons: [
|
|
130
|
+
{ code: 'PRACTICAL_COMMUTE', routeMinutes: 14 },
|
|
131
|
+
{ code: 'QUALIFICATIONS_PARTIAL', matched: 2, required: 3 },
|
|
132
|
+
],
|
|
133
|
+
modelVersion: 'candidate-call-priority-v2',
|
|
134
|
+
computedAt: '2026-08-23T09:00:00.000Z',
|
|
135
|
+
decisionEvidence: {
|
|
136
|
+
proximity: {
|
|
137
|
+
score: 0.72,
|
|
138
|
+
routeMinutes: 14,
|
|
139
|
+
maxTravelMinutes: 50,
|
|
140
|
+
distanceKm: 5.2,
|
|
141
|
+
driveMinutes: 22,
|
|
142
|
+
transitMinutes: 48,
|
|
143
|
+
},
|
|
144
|
+
qualification: {
|
|
145
|
+
score: 0.8,
|
|
146
|
+
required: 3,
|
|
147
|
+
matched: 2,
|
|
148
|
+
explicit: true,
|
|
149
|
+
},
|
|
150
|
+
reliability: {
|
|
151
|
+
score: 0.76,
|
|
152
|
+
workerPositiveOutcomes: 6,
|
|
153
|
+
workerMatureOutcomes: 7,
|
|
154
|
+
tradePositiveOutcomes: 15,
|
|
155
|
+
tradeMatureOutcomes: 20,
|
|
156
|
+
globalPrior: 0.6,
|
|
157
|
+
},
|
|
158
|
+
readiness: {
|
|
159
|
+
score: 1,
|
|
160
|
+
state: 'CURRENT_OPEN',
|
|
161
|
+
offerOpenness: 'OPEN',
|
|
162
|
+
offerOpennessSetAt: '2026-08-22T09:00:00.000Z',
|
|
163
|
+
},
|
|
164
|
+
continuity: {
|
|
165
|
+
boost: 14.3,
|
|
166
|
+
outcome: 'CONNECTED',
|
|
167
|
+
acquiredAt: '2026-08-22T08:00:00.000Z',
|
|
168
|
+
expiresAt: '2026-08-24T08:00:00.000Z',
|
|
169
|
+
},
|
|
170
|
+
confidenceFlags: {
|
|
171
|
+
qualificationsExplicit: true,
|
|
172
|
+
matureReliability: true,
|
|
173
|
+
readinessCurrent: true,
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
it('rejects half-populated candidate rankings', () => {
|
|
179
|
+
expect(jobs_tab_contract_1.CandidateRowSchema.safeParse({
|
|
180
|
+
...row,
|
|
181
|
+
ranking: { score: 84, rank: 1 },
|
|
182
|
+
}).success).toBe(false);
|
|
183
|
+
});
|
|
184
|
+
it('rejects candidate rankings outside their score bounds', () => {
|
|
185
|
+
expect(jobs_tab_contract_1.CandidateRowSchema.safeParse({
|
|
186
|
+
...row,
|
|
187
|
+
ranking: {
|
|
188
|
+
score: 101,
|
|
189
|
+
rank: 1,
|
|
190
|
+
baseFit: 82,
|
|
191
|
+
continuityBoost: 14.3,
|
|
192
|
+
confidence: 'MEDIUM',
|
|
193
|
+
reasons: [{ code: 'PRACTICAL_COMMUTE', routeMinutes: 14 }],
|
|
194
|
+
modelVersion: 'candidate-call-priority-v2',
|
|
195
|
+
computedAt: '2026-08-23T09:00:00.000Z',
|
|
196
|
+
},
|
|
197
|
+
}).success).toBe(false);
|
|
198
|
+
});
|
|
199
|
+
it('rejects unknown ranking confidence and mismatched reason payloads', () => {
|
|
200
|
+
const ranking = {
|
|
201
|
+
score: 84,
|
|
202
|
+
rank: 1,
|
|
203
|
+
baseFit: 82,
|
|
204
|
+
continuityBoost: 14.3,
|
|
205
|
+
confidence: 'MEDIUM',
|
|
206
|
+
reasons: [{ code: 'PRACTICAL_COMMUTE', routeMinutes: 14 }],
|
|
207
|
+
modelVersion: 'candidate-call-priority-v2',
|
|
208
|
+
computedAt: '2026-08-23T09:00:00.000Z',
|
|
209
|
+
};
|
|
210
|
+
expect(jobs_tab_contract_1.CandidateRowSchema.safeParse({
|
|
211
|
+
...row,
|
|
212
|
+
ranking: { ...ranking, confidence: 'UNKNOWN' },
|
|
213
|
+
}).success).toBe(false);
|
|
214
|
+
expect(jobs_tab_contract_1.CandidateRowSchema.safeParse({
|
|
215
|
+
...row,
|
|
216
|
+
ranking: {
|
|
217
|
+
...ranking,
|
|
218
|
+
reasons: [{ code: 'PRACTICAL_COMMUTE', matched: 2, required: 3 }],
|
|
219
|
+
},
|
|
220
|
+
}).success).toBe(false);
|
|
221
|
+
});
|
|
59
222
|
it('parses a never-contacted row (nullables)', () => {
|
|
60
223
|
const parsed = jobs_tab_contract_1.CandidateRowSchema.parse({
|
|
61
224
|
...row,
|
|
@@ -81,8 +244,10 @@ describe('JobCandidates schemas', () => {
|
|
|
81
244
|
const parsed = jobs_tab_contract_1.CandidateRowSchema.parse(row);
|
|
82
245
|
expect(parsed.offerChannels).toBeUndefined();
|
|
83
246
|
expect(parsed.offerContactedAt).toBeUndefined();
|
|
247
|
+
expect(parsed.ranking).toBeUndefined();
|
|
84
248
|
});
|
|
85
249
|
it('parses the response envelope', () => {
|
|
250
|
+
const snapshotId = '00000000-0000-4000-8000-000000000001';
|
|
86
251
|
const parsed = jobs_tab_contract_1.JobCandidatesResponseSchema.parse({
|
|
87
252
|
owned: [row],
|
|
88
253
|
curated: [],
|
|
@@ -96,10 +261,24 @@ describe('JobCandidates schemas', () => {
|
|
|
96
261
|
workersContactedByViewerCount: 0,
|
|
97
262
|
workersContactedByOthersCount: 0,
|
|
98
263
|
dismissed: [],
|
|
264
|
+
orderSnapshot: {
|
|
265
|
+
snapshotId,
|
|
266
|
+
mode: 'RANKED',
|
|
267
|
+
modelVersion: 'candidate-call-priority-v2',
|
|
268
|
+
computedAt: '2026-08-23T09:00:00.000Z',
|
|
269
|
+
rankedCandidateCount: 1,
|
|
270
|
+
},
|
|
99
271
|
});
|
|
100
272
|
expect(parsed.totalOwned).toBe(1);
|
|
101
273
|
expect(parsed.page).toBe(1);
|
|
102
274
|
expect(parsed.cards.own[0]?.id).toBe(row.subjectId);
|
|
275
|
+
expect(parsed).toMatchObject({
|
|
276
|
+
orderSnapshot: {
|
|
277
|
+
snapshotId,
|
|
278
|
+
mode: 'RANKED',
|
|
279
|
+
rankedCandidateCount: 1,
|
|
280
|
+
},
|
|
281
|
+
});
|
|
103
282
|
});
|
|
104
283
|
it('requires the atomic candidate card projection', () => {
|
|
105
284
|
expect(() => jobs_tab_contract_1.JobCandidatesResponseSchema.parse({
|