@nexalink/coding-contracts 0.2.0 → 0.3.0

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.
@@ -2,7 +2,20 @@
2
2
  // GENERATED FILE. DO NOT EDIT.
3
3
  // Source: coding-contracts schemas/ (run: bun run contracts:gen)
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.RcmWorkflowCatalogSchemaJson = exports.validRcmWorkflowCatalog = exports.rcmWorkflowCatalogSchema = exports.RcmRuntimeEventSchemaJson = exports.validRcmRuntimeEvent = exports.rcmRuntimeEventSchema = exports.RcmRetrievalMetadataSchemaJson = exports.validRcmRetrievalMetadata = exports.rcmRetrievalMetadataSchema = exports.RcmModelPromptSchemaJson = exports.validRcmModelPrompt = exports.rcmModelPromptSchema = exports.RcmCodingOutputSchemaJson = exports.validRcmCodingOutput = exports.rcmCodingOutputSchema = exports.RcmCodingInputSchemaJson = exports.validRcmCodingInput = exports.rcmCodingInputSchema = exports.RcmSupportingReferenceSchemaJson = exports.validRcmSupportingReference = exports.rcmSupportingReferenceSchema = exports.RCM_WORKFLOW_CATALOG_SCHEMA_VERSION = exports.RCM_RUNTIME_EVENT_SCHEMA_VERSION = exports.RCM_RETRIEVAL_SCHEMA_VERSION = exports.RCM_MODEL_PROMPT_SCHEMA_VERSION = exports.RCM_OUTPUT_SCHEMA_VERSION = exports.RCM_INPUT_SCHEMA_VERSION = exports.RCM_REFERENCE_SCHEMA_VERSION = exports.RCM_HUMAN_REVIEW_INSTRUCTION = exports.RCM_OUTPUT_SCHEMA_NAME = exports.RCM_HUMAN_REVIEW_POLICY_ID = exports.RCM_MODEL_POLICY_ID = exports.RCM_WORKFLOW_ID = void 0;
5
+ exports.validCodingEvidence = exports.codingEvidenceSchema = exports.CodingDecisionLineSchemaJson = exports.validCodingDecisionLine = exports.codingDecisionLineSchema = exports.CodingBatchSchemaJson = exports.validCodingBatch = exports.codingBatchSchema = exports.CodingCaseSchemaJson = exports.validCodingCase = exports.codingCaseSchema = exports.CodingExtensionSchemaJson = exports.validCodingExtension = exports.codingExtensionSchema = exports.CodingServiceLineSchemaJson = exports.validCodingServiceLine = exports.codingServiceLineSchema = exports.CodingCaseClinicalSchemaJson = exports.validCodingCaseClinical = exports.codingCaseClinicalSchema = exports.CodingCasePayerSchemaJson = exports.validCodingCasePayer = exports.codingCasePayerSchema = exports.CodingCaseContextSchemaJson = exports.validCodingCaseContext = exports.codingCaseContextSchema = exports.RCM_WORKFLOW_CATALOG_SCHEMA_VERSION = exports.RCM_RUNTIME_EVENT_SCHEMA_VERSION = exports.RCM_RETRIEVAL_SCHEMA_VERSION = exports.RCM_MODEL_PROMPT_SCHEMA_VERSION = exports.RCM_OUTPUT_SCHEMA_VERSION = exports.RCM_INPUT_SCHEMA_VERSION = exports.RCM_REFERENCE_SCHEMA_VERSION = exports.CODING_DECISION_SCHEMA_VERSION = exports.CODING_REVIEWER_ACTION_SCHEMA_VERSION = exports.CODING_RULE_RESULT_SCHEMA_VERSION = exports.CODING_EVIDENCE_SCHEMA_VERSION = exports.CODING_DECISION_LINE_SCHEMA_VERSION = exports.CODING_BATCH_SCHEMA_VERSION = exports.CODING_CASE_SCHEMA_VERSION = exports.CODING_EXTENSION_SCHEMA_VERSION = exports.CODING_SERVICE_LINE_SCHEMA_VERSION = exports.CODING_CASE_CLINICAL_SCHEMA_VERSION = exports.CODING_CASE_PAYER_SCHEMA_VERSION = exports.CODING_CASE_CONTEXT_SCHEMA_VERSION = exports.RCM_HUMAN_REVIEW_INSTRUCTION = exports.RCM_OUTPUT_SCHEMA_NAME = exports.RCM_HUMAN_REVIEW_POLICY_ID = exports.RCM_MODEL_POLICY_ID = exports.RCM_WORKFLOW_ID = void 0;
6
+ exports.RcmWorkflowCatalogSchemaJson = exports.validRcmWorkflowCatalog = exports.rcmWorkflowCatalogSchema = exports.RcmRuntimeEventSchemaJson = exports.validRcmRuntimeEvent = exports.rcmRuntimeEventSchema = exports.RcmRetrievalMetadataSchemaJson = exports.validRcmRetrievalMetadata = exports.rcmRetrievalMetadataSchema = exports.RcmModelPromptSchemaJson = exports.validRcmModelPrompt = exports.rcmModelPromptSchema = exports.RcmCodingOutputSchemaJson = exports.validRcmCodingOutput = exports.rcmCodingOutputSchema = exports.RcmCodingInputSchemaJson = exports.validRcmCodingInput = exports.rcmCodingInputSchema = exports.RcmSupportingReferenceSchemaJson = exports.validRcmSupportingReference = exports.rcmSupportingReferenceSchema = exports.CodingDecisionSchemaJson = exports.validCodingDecision = exports.codingDecisionSchema = exports.CodingReviewerActionSchemaJson = exports.validCodingReviewerAction = exports.codingReviewerActionSchema = exports.CodingRuleResultSchemaJson = exports.validCodingRuleResult = exports.codingRuleResultSchema = exports.CodingEvidenceSchemaJson = void 0;
7
+ exports.codingCaseContextValidationError = codingCaseContextValidationError;
8
+ exports.codingCasePayerValidationError = codingCasePayerValidationError;
9
+ exports.codingCaseClinicalValidationError = codingCaseClinicalValidationError;
10
+ exports.codingServiceLineValidationError = codingServiceLineValidationError;
11
+ exports.codingExtensionValidationError = codingExtensionValidationError;
12
+ exports.codingCaseValidationError = codingCaseValidationError;
13
+ exports.codingBatchValidationError = codingBatchValidationError;
14
+ exports.codingDecisionLineValidationError = codingDecisionLineValidationError;
15
+ exports.codingEvidenceValidationError = codingEvidenceValidationError;
16
+ exports.codingRuleResultValidationError = codingRuleResultValidationError;
17
+ exports.codingReviewerActionValidationError = codingReviewerActionValidationError;
18
+ exports.codingDecisionValidationError = codingDecisionValidationError;
6
19
  exports.rcmSupportingReferenceValidationError = rcmSupportingReferenceValidationError;
7
20
  exports.rcmCodingInputValidationError = rcmCodingInputValidationError;
8
21
  exports.rcmCodingOutputValidationError = rcmCodingOutputValidationError;
@@ -13,6 +26,38 @@ exports.rcmWorkflowCatalogValidationError = rcmWorkflowCatalogValidationError;
13
26
  const zod_1 = require("zod");
14
27
  const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
15
28
  const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
29
+ const ISO_DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
30
+ const isIsoDate = (value) => {
31
+ const match = ISO_DATE_PATTERN.exec(value);
32
+ if (!match)
33
+ return false;
34
+ const year = Number(match[1]);
35
+ const month = Number(match[2]);
36
+ const day = Number(match[3]);
37
+ if (year < 1 || month < 1 || month > 12)
38
+ return false;
39
+ const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
40
+ const daysInMonth = [
41
+ 31,
42
+ leapYear ? 29 : 28,
43
+ 31,
44
+ 30,
45
+ 31,
46
+ 30,
47
+ 31,
48
+ 31,
49
+ 30,
50
+ 31,
51
+ 30,
52
+ 31,
53
+ ];
54
+ return day >= 1 && day <= daysInMonth[month - 1];
55
+ };
56
+ const RFC3339_DATETIME_PATTERN = /^(\d{4}-\d{2}-\d{2})T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/;
57
+ const isRfc3339DateTime = (value) => {
58
+ const match = RFC3339_DATETIME_PATTERN.exec(value);
59
+ return match !== null && isIsoDate(match[1]);
60
+ };
16
61
  // Canonical workflow constants (source: workflow-constants.json).
17
62
  exports.RCM_WORKFLOW_ID = "rcm-coding-assistance";
18
63
  exports.RCM_MODEL_POLICY_ID = "carecompass-rcm-review-v1";
@@ -20,6 +65,18 @@ exports.RCM_HUMAN_REVIEW_POLICY_ID = "qualified-coder-review-v1";
20
65
  exports.RCM_OUTPUT_SCHEMA_NAME = "carecompass_rcm_grounded_review";
21
66
  exports.RCM_HUMAN_REVIEW_INSTRUCTION = "Qualified human coder review is required before billing, coding, or claim submission.";
22
67
  // Schema wire versions (source: schemas/*.schema.json).
68
+ exports.CODING_CASE_CONTEXT_SCHEMA_VERSION = "coding-case-context-v1";
69
+ exports.CODING_CASE_PAYER_SCHEMA_VERSION = "coding-case-payer-v1";
70
+ exports.CODING_CASE_CLINICAL_SCHEMA_VERSION = "coding-case-clinical-v1";
71
+ exports.CODING_SERVICE_LINE_SCHEMA_VERSION = "coding-service-line-v1";
72
+ exports.CODING_EXTENSION_SCHEMA_VERSION = "coding-extension-v1";
73
+ exports.CODING_CASE_SCHEMA_VERSION = "coding-case-v1";
74
+ exports.CODING_BATCH_SCHEMA_VERSION = "coding-batch-v1";
75
+ exports.CODING_DECISION_LINE_SCHEMA_VERSION = "coding-decision-line-v1";
76
+ exports.CODING_EVIDENCE_SCHEMA_VERSION = "coding-evidence-v1";
77
+ exports.CODING_RULE_RESULT_SCHEMA_VERSION = "coding-rule-result-v1";
78
+ exports.CODING_REVIEWER_ACTION_SCHEMA_VERSION = "coding-reviewer-action-v1";
79
+ exports.CODING_DECISION_SCHEMA_VERSION = "coding-decision-v1";
23
80
  exports.RCM_REFERENCE_SCHEMA_VERSION = "rcm-supporting-reference-v1";
24
81
  exports.RCM_INPUT_SCHEMA_VERSION = "rcm-coding-input-v1";
25
82
  exports.RCM_OUTPUT_SCHEMA_VERSION = "rcm-grounded-human-review-v2";
@@ -28,6 +85,4171 @@ exports.RCM_RETRIEVAL_SCHEMA_VERSION = "rcm-retrieval-metadata-v1";
28
85
  exports.RCM_RUNTIME_EVENT_SCHEMA_VERSION = "rcm-runtime-event-v1";
29
86
  exports.RCM_WORKFLOW_CATALOG_SCHEMA_VERSION = "rcm-workflow-catalog-v1";
30
87
  // --------------------------------------------------------------------
88
+ // CodingCaseContext (schema 1.0.0, wire coding-case-context-v1)
89
+ // --------------------------------------------------------------------
90
+ exports.codingCaseContextSchema = zod_1.z
91
+ .object({
92
+ setting: zod_1.z.enum([
93
+ "professional",
94
+ "facility",
95
+ "pharmacy",
96
+ "dental",
97
+ "risk_adjustment",
98
+ "other",
99
+ ]),
100
+ otherSettingDescription: zod_1.z
101
+ .string()
102
+ .min(1)
103
+ .max(120)
104
+ .refine((value) => value.trim().length > 0)
105
+ .optional(),
106
+ placeOfService: zod_1.z.string().regex(new RegExp("^[0-9]{2}$")).optional(),
107
+ jurisdiction: zod_1.z.string().min(1).max(80).optional(),
108
+ specialty: zod_1.z.string().min(1).max(120).optional(),
109
+ provider: zod_1.z
110
+ .object({
111
+ providerId: zod_1.z.string().min(1).max(64).optional(),
112
+ npi: zod_1.z.string().regex(new RegExp("^[0-9]{10}$")).optional(),
113
+ name: zod_1.z.string().min(1).max(160).optional(),
114
+ role: zod_1.z
115
+ .enum([
116
+ "rendering",
117
+ "billing",
118
+ "attending",
119
+ "supervising",
120
+ "ordering",
121
+ "referring",
122
+ "other",
123
+ ])
124
+ .optional(),
125
+ taxonomy: zod_1.z.string().min(1).max(40).optional(),
126
+ })
127
+ .strict()
128
+ .optional(),
129
+ facility: zod_1.z
130
+ .object({
131
+ facilityId: zod_1.z.string().min(1).max(64).optional(),
132
+ name: zod_1.z.string().min(1).max(160).optional(),
133
+ facilityType: zod_1.z
134
+ .enum([
135
+ "hospital_inpatient",
136
+ "hospital_outpatient",
137
+ "clinic",
138
+ "ambulatory_surgery_center",
139
+ "nursing_facility",
140
+ "other",
141
+ ])
142
+ .optional(),
143
+ })
144
+ .strict()
145
+ .optional(),
146
+ })
147
+ .strict();
148
+ function codingCaseContextValidationError(value) {
149
+ if (!isRecord(value))
150
+ return "context";
151
+ if (!["setting"].every((key) => key in value))
152
+ return "context_keys";
153
+ if (!Object.keys(value).every((key) => [
154
+ "setting",
155
+ "otherSettingDescription",
156
+ "placeOfService",
157
+ "jurisdiction",
158
+ "specialty",
159
+ "provider",
160
+ "facility",
161
+ ].includes(key)))
162
+ return "context_keys";
163
+ const value_setting = value["setting"];
164
+ if (typeof value_setting !== "string" ||
165
+ ![
166
+ "professional",
167
+ "facility",
168
+ "pharmacy",
169
+ "dental",
170
+ "risk_adjustment",
171
+ "other",
172
+ ].includes(value_setting))
173
+ return "context_setting";
174
+ if (value["otherSettingDescription"] !== undefined) {
175
+ const value_otherSettingDescription = value["otherSettingDescription"];
176
+ if (typeof value_otherSettingDescription !== "string" ||
177
+ value_otherSettingDescription.length < 1 ||
178
+ value_otherSettingDescription.length > 120 ||
179
+ value_otherSettingDescription.trim().length === 0)
180
+ return "context_other_setting";
181
+ }
182
+ if (value["placeOfService"] !== undefined) {
183
+ const value_placeOfService = value["placeOfService"];
184
+ if (typeof value_placeOfService !== "string" ||
185
+ !new RegExp("^[0-9]{2}$").test(value_placeOfService))
186
+ return "context_place_of_service";
187
+ }
188
+ if (value["jurisdiction"] !== undefined) {
189
+ const value_jurisdiction = value["jurisdiction"];
190
+ if (typeof value_jurisdiction !== "string" ||
191
+ value_jurisdiction.length < 1 ||
192
+ value_jurisdiction.length > 80)
193
+ return "context_jurisdiction";
194
+ }
195
+ if (value["specialty"] !== undefined) {
196
+ const value_specialty = value["specialty"];
197
+ if (typeof value_specialty !== "string" ||
198
+ value_specialty.length < 1 ||
199
+ value_specialty.length > 120)
200
+ return "context_specialty";
201
+ }
202
+ if (value["provider"] !== undefined) {
203
+ const value_provider = value["provider"];
204
+ if (!isRecord(value_provider))
205
+ return "context_provider";
206
+ if (!Object.keys(value_provider).every((key) => ["providerId", "npi", "name", "role", "taxonomy"].includes(key)))
207
+ return "context_provider_keys";
208
+ if (value_provider["providerId"] !== undefined) {
209
+ const value_provider_providerId = value_provider["providerId"];
210
+ if (typeof value_provider_providerId !== "string" ||
211
+ value_provider_providerId.length < 1 ||
212
+ value_provider_providerId.length > 64)
213
+ return "context_provider_id";
214
+ }
215
+ if (value_provider["npi"] !== undefined) {
216
+ const value_provider_npi = value_provider["npi"];
217
+ if (typeof value_provider_npi !== "string" ||
218
+ !new RegExp("^[0-9]{10}$").test(value_provider_npi))
219
+ return "context_provider_npi";
220
+ }
221
+ if (value_provider["name"] !== undefined) {
222
+ const value_provider_name = value_provider["name"];
223
+ if (typeof value_provider_name !== "string" ||
224
+ value_provider_name.length < 1 ||
225
+ value_provider_name.length > 160)
226
+ return "context_provider_name";
227
+ }
228
+ if (value_provider["role"] !== undefined) {
229
+ const value_provider_role = value_provider["role"];
230
+ if (typeof value_provider_role !== "string" ||
231
+ ![
232
+ "rendering",
233
+ "billing",
234
+ "attending",
235
+ "supervising",
236
+ "ordering",
237
+ "referring",
238
+ "other",
239
+ ].includes(value_provider_role))
240
+ return "context_provider_role";
241
+ }
242
+ if (value_provider["taxonomy"] !== undefined) {
243
+ const value_provider_taxonomy = value_provider["taxonomy"];
244
+ if (typeof value_provider_taxonomy !== "string" ||
245
+ value_provider_taxonomy.length < 1 ||
246
+ value_provider_taxonomy.length > 40)
247
+ return "context_provider_taxonomy";
248
+ }
249
+ }
250
+ if (value["facility"] !== undefined) {
251
+ const value_facility = value["facility"];
252
+ if (!isRecord(value_facility))
253
+ return "context_facility";
254
+ if (!Object.keys(value_facility).every((key) => ["facilityId", "name", "facilityType"].includes(key)))
255
+ return "context_facility_keys";
256
+ if (value_facility["facilityId"] !== undefined) {
257
+ const value_facility_facilityId = value_facility["facilityId"];
258
+ if (typeof value_facility_facilityId !== "string" ||
259
+ value_facility_facilityId.length < 1 ||
260
+ value_facility_facilityId.length > 64)
261
+ return "context_facility_id";
262
+ }
263
+ if (value_facility["name"] !== undefined) {
264
+ const value_facility_name = value_facility["name"];
265
+ if (typeof value_facility_name !== "string" ||
266
+ value_facility_name.length < 1 ||
267
+ value_facility_name.length > 160)
268
+ return "context_facility_name";
269
+ }
270
+ if (value_facility["facilityType"] !== undefined) {
271
+ const value_facility_facilityType = value_facility["facilityType"];
272
+ if (typeof value_facility_facilityType !== "string" ||
273
+ ![
274
+ "hospital_inpatient",
275
+ "hospital_outpatient",
276
+ "clinic",
277
+ "ambulatory_surgery_center",
278
+ "nursing_facility",
279
+ "other",
280
+ ].includes(value_facility_facilityType))
281
+ return "context_facility_type";
282
+ }
283
+ }
284
+ return null;
285
+ }
286
+ const validCodingCaseContext = (value) => codingCaseContextValidationError(value) === null;
287
+ exports.validCodingCaseContext = validCodingCaseContext;
288
+ exports.CodingCaseContextSchemaJson = {
289
+ $schema: "https://json-schema.org/draft/2020-12/schema",
290
+ $id: "https://nexalink.care/contracts/coding-case-context.schema.json",
291
+ title: "CodingCaseContext",
292
+ description: "Where and by whom the services were rendered: setting, place of service, jurisdiction, specialty, provider, and facility. Provider identifiers are direct identifiers and must never be promoted to analytics surfaces.",
293
+ version: "1.0.0",
294
+ type: "object",
295
+ additionalProperties: false,
296
+ required: ["setting"],
297
+ properties: {
298
+ setting: {
299
+ type: "string",
300
+ enum: [
301
+ "professional",
302
+ "facility",
303
+ "pharmacy",
304
+ "dental",
305
+ "risk_adjustment",
306
+ "other",
307
+ ],
308
+ },
309
+ otherSettingDescription: {
310
+ type: "string",
311
+ minLength: 1,
312
+ maxLength: 120,
313
+ },
314
+ placeOfService: {
315
+ type: "string",
316
+ pattern: "^[0-9]{2}$",
317
+ },
318
+ jurisdiction: {
319
+ type: "string",
320
+ minLength: 1,
321
+ maxLength: 80,
322
+ },
323
+ specialty: {
324
+ type: "string",
325
+ minLength: 1,
326
+ maxLength: 120,
327
+ },
328
+ provider: {
329
+ type: "object",
330
+ additionalProperties: false,
331
+ properties: {
332
+ providerId: {
333
+ type: "string",
334
+ minLength: 1,
335
+ maxLength: 64,
336
+ },
337
+ npi: {
338
+ type: "string",
339
+ pattern: "^[0-9]{10}$",
340
+ },
341
+ name: {
342
+ type: "string",
343
+ minLength: 1,
344
+ maxLength: 160,
345
+ },
346
+ role: {
347
+ type: "string",
348
+ enum: [
349
+ "rendering",
350
+ "billing",
351
+ "attending",
352
+ "supervising",
353
+ "ordering",
354
+ "referring",
355
+ "other",
356
+ ],
357
+ },
358
+ taxonomy: {
359
+ type: "string",
360
+ minLength: 1,
361
+ maxLength: 40,
362
+ },
363
+ },
364
+ },
365
+ facility: {
366
+ type: "object",
367
+ additionalProperties: false,
368
+ properties: {
369
+ facilityId: {
370
+ type: "string",
371
+ minLength: 1,
372
+ maxLength: 64,
373
+ },
374
+ name: {
375
+ type: "string",
376
+ minLength: 1,
377
+ maxLength: 160,
378
+ },
379
+ facilityType: {
380
+ type: "string",
381
+ enum: [
382
+ "hospital_inpatient",
383
+ "hospital_outpatient",
384
+ "clinic",
385
+ "ambulatory_surgery_center",
386
+ "nursing_facility",
387
+ "other",
388
+ ],
389
+ },
390
+ },
391
+ },
392
+ },
393
+ };
394
+ // --------------------------------------------------------------------
395
+ // CodingCasePayer (schema 1.0.0, wire coding-case-payer-v1)
396
+ // --------------------------------------------------------------------
397
+ exports.codingCasePayerSchema = zod_1.z
398
+ .object({
399
+ payerName: zod_1.z
400
+ .string()
401
+ .min(1)
402
+ .max(200)
403
+ .refine((value) => value.trim().length > 0),
404
+ payerId: zod_1.z.string().min(1).max(120).optional(),
405
+ lineOfBusiness: zod_1.z
406
+ .enum(["commercial", "government", "self_pay", "other"])
407
+ .optional(),
408
+ memberId: zod_1.z.string().min(1).max(120).optional(),
409
+ plan: zod_1.z
410
+ .object({
411
+ planName: zod_1.z.string().min(1).max(200).optional(),
412
+ planId: zod_1.z.string().min(1).max(120).optional(),
413
+ })
414
+ .strict()
415
+ .optional(),
416
+ program: zod_1.z
417
+ .object({
418
+ programName: zod_1.z.string().min(1).max(160).optional(),
419
+ programCode: zod_1.z.string().min(1).max(80).optional(),
420
+ })
421
+ .strict()
422
+ .optional(),
423
+ contract: zod_1.z
424
+ .object({
425
+ contractId: zod_1.z.string().min(1).max(120).optional(),
426
+ contractVersion: zod_1.z.string().min(1).max(40).optional(),
427
+ effectiveDate: zod_1.z
428
+ .string()
429
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
430
+ .refine(isIsoDate)
431
+ .optional(),
432
+ })
433
+ .strict()
434
+ .optional(),
435
+ mac: zod_1.z
436
+ .object({
437
+ macId: zod_1.z.string().min(1).max(40).optional(),
438
+ jurisdiction: zod_1.z.string().min(1).max(80).optional(),
439
+ })
440
+ .strict()
441
+ .optional(),
442
+ })
443
+ .strict();
444
+ function codingCasePayerValidationError(value) {
445
+ if (!isRecord(value))
446
+ return "payer";
447
+ if (!["payerName"].every((key) => key in value))
448
+ return "payer_keys";
449
+ if (!Object.keys(value).every((key) => [
450
+ "payerName",
451
+ "payerId",
452
+ "lineOfBusiness",
453
+ "memberId",
454
+ "plan",
455
+ "program",
456
+ "contract",
457
+ "mac",
458
+ ].includes(key)))
459
+ return "payer_keys";
460
+ const value_payerName = value["payerName"];
461
+ if (typeof value_payerName !== "string" ||
462
+ value_payerName.length < 1 ||
463
+ value_payerName.length > 200 ||
464
+ value_payerName.trim().length === 0)
465
+ return "payer_name";
466
+ if (value["payerId"] !== undefined) {
467
+ const value_payerId = value["payerId"];
468
+ if (typeof value_payerId !== "string" ||
469
+ value_payerId.length < 1 ||
470
+ value_payerId.length > 120)
471
+ return "payer_id";
472
+ }
473
+ if (value["lineOfBusiness"] !== undefined) {
474
+ const value_lineOfBusiness = value["lineOfBusiness"];
475
+ if (typeof value_lineOfBusiness !== "string" ||
476
+ !["commercial", "government", "self_pay", "other"].includes(value_lineOfBusiness))
477
+ return "payer_line_of_business";
478
+ }
479
+ if (value["memberId"] !== undefined) {
480
+ const value_memberId = value["memberId"];
481
+ if (typeof value_memberId !== "string" ||
482
+ value_memberId.length < 1 ||
483
+ value_memberId.length > 120)
484
+ return "payer_member_id";
485
+ }
486
+ if (value["plan"] !== undefined) {
487
+ const value_plan = value["plan"];
488
+ if (!isRecord(value_plan))
489
+ return "payer_plan";
490
+ if (!Object.keys(value_plan).every((key) => ["planName", "planId"].includes(key)))
491
+ return "payer_plan_keys";
492
+ if (value_plan["planName"] !== undefined) {
493
+ const value_plan_planName = value_plan["planName"];
494
+ if (typeof value_plan_planName !== "string" ||
495
+ value_plan_planName.length < 1 ||
496
+ value_plan_planName.length > 200)
497
+ return "payer_plan_name";
498
+ }
499
+ if (value_plan["planId"] !== undefined) {
500
+ const value_plan_planId = value_plan["planId"];
501
+ if (typeof value_plan_planId !== "string" ||
502
+ value_plan_planId.length < 1 ||
503
+ value_plan_planId.length > 120)
504
+ return "payer_plan_id";
505
+ }
506
+ }
507
+ if (value["program"] !== undefined) {
508
+ const value_program = value["program"];
509
+ if (!isRecord(value_program))
510
+ return "payer_program";
511
+ if (!Object.keys(value_program).every((key) => ["programName", "programCode"].includes(key)))
512
+ return "payer_program_keys";
513
+ if (value_program["programName"] !== undefined) {
514
+ const value_program_programName = value_program["programName"];
515
+ if (typeof value_program_programName !== "string" ||
516
+ value_program_programName.length < 1 ||
517
+ value_program_programName.length > 160)
518
+ return "payer_program_name";
519
+ }
520
+ if (value_program["programCode"] !== undefined) {
521
+ const value_program_programCode = value_program["programCode"];
522
+ if (typeof value_program_programCode !== "string" ||
523
+ value_program_programCode.length < 1 ||
524
+ value_program_programCode.length > 80)
525
+ return "payer_program_code";
526
+ }
527
+ }
528
+ if (value["contract"] !== undefined) {
529
+ const value_contract = value["contract"];
530
+ if (!isRecord(value_contract))
531
+ return "payer_contract";
532
+ if (!Object.keys(value_contract).every((key) => ["contractId", "contractVersion", "effectiveDate"].includes(key)))
533
+ return "payer_contract_keys";
534
+ if (value_contract["contractId"] !== undefined) {
535
+ const value_contract_contractId = value_contract["contractId"];
536
+ if (typeof value_contract_contractId !== "string" ||
537
+ value_contract_contractId.length < 1 ||
538
+ value_contract_contractId.length > 120)
539
+ return "payer_contract_id";
540
+ }
541
+ if (value_contract["contractVersion"] !== undefined) {
542
+ const value_contract_contractVersion = value_contract["contractVersion"];
543
+ if (typeof value_contract_contractVersion !== "string" ||
544
+ value_contract_contractVersion.length < 1 ||
545
+ value_contract_contractVersion.length > 40)
546
+ return "payer_contract_version";
547
+ }
548
+ if (value_contract["effectiveDate"] !== undefined) {
549
+ const value_contract_effectiveDate = value_contract["effectiveDate"];
550
+ if (typeof value_contract_effectiveDate !== "string" ||
551
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(value_contract_effectiveDate) ||
552
+ !isIsoDate(value_contract_effectiveDate))
553
+ return "payer_contract_effective_date";
554
+ }
555
+ }
556
+ if (value["mac"] !== undefined) {
557
+ const value_mac = value["mac"];
558
+ if (!isRecord(value_mac))
559
+ return "payer_mac";
560
+ if (!Object.keys(value_mac).every((key) => ["macId", "jurisdiction"].includes(key)))
561
+ return "payer_mac_keys";
562
+ if (value_mac["macId"] !== undefined) {
563
+ const value_mac_macId = value_mac["macId"];
564
+ if (typeof value_mac_macId !== "string" ||
565
+ value_mac_macId.length < 1 ||
566
+ value_mac_macId.length > 40)
567
+ return "payer_mac_id";
568
+ }
569
+ if (value_mac["jurisdiction"] !== undefined) {
570
+ const value_mac_jurisdiction = value_mac["jurisdiction"];
571
+ if (typeof value_mac_jurisdiction !== "string" ||
572
+ value_mac_jurisdiction.length < 1 ||
573
+ value_mac_jurisdiction.length > 80)
574
+ return "payer_mac_jurisdiction";
575
+ }
576
+ }
577
+ return null;
578
+ }
579
+ const validCodingCasePayer = (value) => codingCasePayerValidationError(value) === null;
580
+ exports.validCodingCasePayer = validCodingCasePayer;
581
+ exports.CodingCasePayerSchemaJson = {
582
+ $schema: "https://json-schema.org/draft/2020-12/schema",
583
+ $id: "https://nexalink.care/contracts/coding-case-payer.schema.json",
584
+ title: "CodingCasePayer",
585
+ description: "Payer, plan, program, contract, and MAC context used to resolve applicability. memberId is a direct identifier and must never leave tenant-scoped storage for analytics surfaces. Contract and program fields are customer configuration, never immutable server policy.",
586
+ version: "1.0.0",
587
+ type: "object",
588
+ additionalProperties: false,
589
+ required: ["payerName"],
590
+ properties: {
591
+ payerName: {
592
+ type: "string",
593
+ minLength: 1,
594
+ maxLength: 200,
595
+ },
596
+ payerId: {
597
+ type: "string",
598
+ minLength: 1,
599
+ maxLength: 120,
600
+ },
601
+ lineOfBusiness: {
602
+ type: "string",
603
+ enum: ["commercial", "government", "self_pay", "other"],
604
+ },
605
+ memberId: {
606
+ type: "string",
607
+ minLength: 1,
608
+ maxLength: 120,
609
+ },
610
+ plan: {
611
+ type: "object",
612
+ additionalProperties: false,
613
+ properties: {
614
+ planName: {
615
+ type: "string",
616
+ minLength: 1,
617
+ maxLength: 200,
618
+ },
619
+ planId: {
620
+ type: "string",
621
+ minLength: 1,
622
+ maxLength: 120,
623
+ },
624
+ },
625
+ },
626
+ program: {
627
+ type: "object",
628
+ additionalProperties: false,
629
+ properties: {
630
+ programName: {
631
+ type: "string",
632
+ minLength: 1,
633
+ maxLength: 160,
634
+ },
635
+ programCode: {
636
+ type: "string",
637
+ minLength: 1,
638
+ maxLength: 80,
639
+ },
640
+ },
641
+ },
642
+ contract: {
643
+ type: "object",
644
+ additionalProperties: false,
645
+ properties: {
646
+ contractId: {
647
+ type: "string",
648
+ minLength: 1,
649
+ maxLength: 120,
650
+ },
651
+ contractVersion: {
652
+ type: "string",
653
+ minLength: 1,
654
+ maxLength: 40,
655
+ },
656
+ effectiveDate: {
657
+ type: "string",
658
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
659
+ format: "date",
660
+ },
661
+ },
662
+ },
663
+ mac: {
664
+ type: "object",
665
+ additionalProperties: false,
666
+ properties: {
667
+ macId: {
668
+ type: "string",
669
+ minLength: 1,
670
+ maxLength: 40,
671
+ },
672
+ jurisdiction: {
673
+ type: "string",
674
+ minLength: 1,
675
+ maxLength: 80,
676
+ },
677
+ },
678
+ },
679
+ },
680
+ };
681
+ // --------------------------------------------------------------------
682
+ // CodingCaseClinical (schema 1.0.0, wire coding-case-clinical-v1)
683
+ // --------------------------------------------------------------------
684
+ exports.codingCaseClinicalSchema = zod_1.z
685
+ .object({
686
+ diagnoses: zod_1.z
687
+ .array(zod_1.z
688
+ .object({
689
+ diagnosisId: zod_1.z.string().min(1).max(60),
690
+ code: zod_1.z.string().min(1).max(32).optional(),
691
+ codeSystem: zod_1.z.enum(["ICD-10-CM", "ICD-9-CM", "OTHER"]).optional(),
692
+ codeVersion: zod_1.z.string().min(1).max(40).optional(),
693
+ description: zod_1.z.string().min(1).max(240).optional(),
694
+ diagnosisType: zod_1.z
695
+ .enum(["principal", "secondary", "complication", "other"])
696
+ .optional(),
697
+ onsetDate: zod_1.z
698
+ .string()
699
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
700
+ .refine(isIsoDate)
701
+ .optional(),
702
+ presentOnAdmission: zod_1.z.boolean().optional(),
703
+ })
704
+ .strict())
705
+ .max(100)
706
+ .optional(),
707
+ procedures: zod_1.z
708
+ .array(zod_1.z
709
+ .object({
710
+ procedureId: zod_1.z.string().min(1).max(60),
711
+ code: zod_1.z.string().min(1).max(64).optional(),
712
+ codeSystem: zod_1.z
713
+ .enum(["CPT", "HCPCS", "ICD-10-PCS", "OTHER"])
714
+ .optional(),
715
+ codeVersion: zod_1.z.string().min(1).max(40).optional(),
716
+ description: zod_1.z.string().min(1).max(240).optional(),
717
+ performedDate: zod_1.z
718
+ .string()
719
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
720
+ .refine(isIsoDate)
721
+ .optional(),
722
+ })
723
+ .strict())
724
+ .max(100)
725
+ .optional(),
726
+ medications: zod_1.z
727
+ .array(zod_1.z
728
+ .object({
729
+ medicationId: zod_1.z.string().min(1).max(60),
730
+ code: zod_1.z.string().min(1).max(64).optional(),
731
+ codeSystem: zod_1.z.enum(["NDC", "RxNorm", "OTHER"]).optional(),
732
+ name: zod_1.z.string().min(1).max(240).optional(),
733
+ dosage: zod_1.z.string().min(1).max(120).optional(),
734
+ route: zod_1.z.string().min(1).max(80).optional(),
735
+ administrationDate: zod_1.z
736
+ .string()
737
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
738
+ .refine(isIsoDate)
739
+ .optional(),
740
+ })
741
+ .strict())
742
+ .max(100)
743
+ .optional(),
744
+ supplies: zod_1.z
745
+ .array(zod_1.z
746
+ .object({
747
+ supplyId: zod_1.z.string().min(1).max(60),
748
+ code: zod_1.z.string().min(1).max(64).optional(),
749
+ codeSystem: zod_1.z.enum(["HCPCS", "NDC", "OTHER"]).optional(),
750
+ name: zod_1.z.string().min(1).max(240).optional(),
751
+ quantity: zod_1.z.number().int().min(0).max(999999).optional(),
752
+ unitOfMeasure: zod_1.z.string().min(1).max(20).optional(),
753
+ supplyDate: zod_1.z
754
+ .string()
755
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
756
+ .refine(isIsoDate)
757
+ .optional(),
758
+ })
759
+ .strict())
760
+ .max(100)
761
+ .optional(),
762
+ timeUnits: zod_1.z
763
+ .array(zod_1.z
764
+ .object({
765
+ timeId: zod_1.z.string().min(1).max(60),
766
+ date: zod_1.z
767
+ .string()
768
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
769
+ .refine(isIsoDate),
770
+ durationMinutes: zod_1.z.number().int().min(1).max(1440),
771
+ activityCode: zod_1.z.string().min(1).max(80).optional(),
772
+ activityDescription: zod_1.z.string().min(1).max(240).optional(),
773
+ clinicianRole: zod_1.z
774
+ .enum([
775
+ "attending",
776
+ "physician",
777
+ "nurse_practitioner",
778
+ "physician_assistant",
779
+ "resident",
780
+ "other",
781
+ ])
782
+ .optional(),
783
+ placeOfService: zod_1.z
784
+ .string()
785
+ .regex(new RegExp("^[0-9]{2}$"))
786
+ .optional(),
787
+ })
788
+ .strict())
789
+ .max(200)
790
+ .optional(),
791
+ notes: zod_1.z
792
+ .array(zod_1.z
793
+ .object({
794
+ noteId: zod_1.z.string().min(1).max(60),
795
+ noteType: zod_1.z.enum([
796
+ "clinical_narrative",
797
+ "procedure_narrative",
798
+ "authorization",
799
+ "correspondence",
800
+ "other",
801
+ ]),
802
+ note: zod_1.z
803
+ .string()
804
+ .min(1)
805
+ .max(10000)
806
+ .refine((value) => value.trim().length > 0),
807
+ })
808
+ .strict())
809
+ .max(50)
810
+ .optional(),
811
+ sourceReferences: zod_1.z
812
+ .array(zod_1.z
813
+ .object({
814
+ sourceId: zod_1.z.string().min(1).max(60),
815
+ sourceLabel: zod_1.z.string().min(1).max(120),
816
+ documentId: zod_1.z.string().min(1).max(240).optional(),
817
+ excerpt: zod_1.z
818
+ .string()
819
+ .min(1)
820
+ .max(2000)
821
+ .refine((value) => value.trim().length > 0)
822
+ .optional(),
823
+ sourceVersion: zod_1.z.string().min(1).max(80).optional(),
824
+ corpusScope: zod_1.z.enum(["base", "tenant"]).optional(),
825
+ publisher: zod_1.z.string().min(1).max(240).optional(),
826
+ effectiveDate: zod_1.z
827
+ .string()
828
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
829
+ .refine(isIsoDate)
830
+ .optional(),
831
+ retrievalDate: zod_1.z
832
+ .string()
833
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
834
+ .refine(isIsoDate)
835
+ .optional(),
836
+ coveredPayerProgram: zod_1.z.string().min(1).max(240).optional(),
837
+ sourceUrl: zod_1.z.string().min(1).max(2048).optional(),
838
+ documentHash: zod_1.z.string().min(1).max(64).optional(),
839
+ capturedAt: zod_1.z
840
+ .string()
841
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
842
+ .refine(isIsoDate)
843
+ .optional(),
844
+ humanReviewRequired: zod_1.z.literal(true).optional(),
845
+ })
846
+ .strict())
847
+ .max(50)
848
+ .optional(),
849
+ })
850
+ .strict();
851
+ function codingCaseClinicalValidationError(value) {
852
+ if (!isRecord(value))
853
+ return "clinical";
854
+ if (!Object.keys(value).every((key) => [
855
+ "diagnoses",
856
+ "procedures",
857
+ "medications",
858
+ "supplies",
859
+ "timeUnits",
860
+ "notes",
861
+ "sourceReferences",
862
+ ].includes(key)))
863
+ return "clinical_keys";
864
+ if (value["diagnoses"] !== undefined) {
865
+ const value_diagnoses = value["diagnoses"];
866
+ if (!Array.isArray(value_diagnoses) || value_diagnoses.length > 100)
867
+ return "clinical_diagnoses";
868
+ for (const item of value_diagnoses) {
869
+ if (!isRecord(item))
870
+ return "clinical_diagnosis";
871
+ if (!["diagnosisId"].every((key) => key in item))
872
+ return "clinical_diagnosis_keys";
873
+ if (!Object.keys(item).every((key) => [
874
+ "diagnosisId",
875
+ "code",
876
+ "codeSystem",
877
+ "codeVersion",
878
+ "description",
879
+ "diagnosisType",
880
+ "onsetDate",
881
+ "presentOnAdmission",
882
+ ].includes(key)))
883
+ return "clinical_diagnosis_keys";
884
+ const item_diagnosisId = item["diagnosisId"];
885
+ if (typeof item_diagnosisId !== "string" ||
886
+ item_diagnosisId.length < 1 ||
887
+ item_diagnosisId.length > 60)
888
+ return "clinical_diagnosis_id";
889
+ if (item["code"] !== undefined) {
890
+ const item_code = item["code"];
891
+ if (typeof item_code !== "string" ||
892
+ item_code.length < 1 ||
893
+ item_code.length > 32)
894
+ return "clinical_diagnosis_code";
895
+ }
896
+ if (item["codeSystem"] !== undefined) {
897
+ const item_codeSystem = item["codeSystem"];
898
+ if (typeof item_codeSystem !== "string" ||
899
+ !["ICD-10-CM", "ICD-9-CM", "OTHER"].includes(item_codeSystem))
900
+ return "clinical_diagnosis_code_system";
901
+ }
902
+ if (item["codeVersion"] !== undefined) {
903
+ const item_codeVersion = item["codeVersion"];
904
+ if (typeof item_codeVersion !== "string" ||
905
+ item_codeVersion.length < 1 ||
906
+ item_codeVersion.length > 40)
907
+ return "clinical_diagnosis_code_version";
908
+ }
909
+ if (item["description"] !== undefined) {
910
+ const item_description = item["description"];
911
+ if (typeof item_description !== "string" ||
912
+ item_description.length < 1 ||
913
+ item_description.length > 240)
914
+ return "clinical_diagnosis_description";
915
+ }
916
+ if (item["diagnosisType"] !== undefined) {
917
+ const item_diagnosisType = item["diagnosisType"];
918
+ if (typeof item_diagnosisType !== "string" ||
919
+ !["principal", "secondary", "complication", "other"].includes(item_diagnosisType))
920
+ return "clinical_diagnosis_type";
921
+ }
922
+ if (item["onsetDate"] !== undefined) {
923
+ const item_onsetDate = item["onsetDate"];
924
+ if (typeof item_onsetDate !== "string" ||
925
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(item_onsetDate) ||
926
+ !isIsoDate(item_onsetDate))
927
+ return "clinical_diagnosis_onset_date";
928
+ }
929
+ if (item["presentOnAdmission"] !== undefined) {
930
+ const item_presentOnAdmission = item["presentOnAdmission"];
931
+ if (typeof item_presentOnAdmission !== "boolean")
932
+ return "clinical_diagnosis_present_on_admission";
933
+ }
934
+ }
935
+ }
936
+ if (value["procedures"] !== undefined) {
937
+ const value_procedures = value["procedures"];
938
+ if (!Array.isArray(value_procedures) || value_procedures.length > 100)
939
+ return "clinical_procedures";
940
+ for (const item of value_procedures) {
941
+ if (!isRecord(item))
942
+ return "clinical_procedure";
943
+ if (!["procedureId"].every((key) => key in item))
944
+ return "clinical_procedure_keys";
945
+ if (!Object.keys(item).every((key) => [
946
+ "procedureId",
947
+ "code",
948
+ "codeSystem",
949
+ "codeVersion",
950
+ "description",
951
+ "performedDate",
952
+ ].includes(key)))
953
+ return "clinical_procedure_keys";
954
+ const item_procedureId = item["procedureId"];
955
+ if (typeof item_procedureId !== "string" ||
956
+ item_procedureId.length < 1 ||
957
+ item_procedureId.length > 60)
958
+ return "clinical_procedure_id";
959
+ if (item["code"] !== undefined) {
960
+ const item_code = item["code"];
961
+ if (typeof item_code !== "string" ||
962
+ item_code.length < 1 ||
963
+ item_code.length > 64)
964
+ return "clinical_procedure_code";
965
+ }
966
+ if (item["codeSystem"] !== undefined) {
967
+ const item_codeSystem = item["codeSystem"];
968
+ if (typeof item_codeSystem !== "string" ||
969
+ !["CPT", "HCPCS", "ICD-10-PCS", "OTHER"].includes(item_codeSystem))
970
+ return "clinical_procedure_code_system";
971
+ }
972
+ if (item["codeVersion"] !== undefined) {
973
+ const item_codeVersion = item["codeVersion"];
974
+ if (typeof item_codeVersion !== "string" ||
975
+ item_codeVersion.length < 1 ||
976
+ item_codeVersion.length > 40)
977
+ return "clinical_procedure_code_version";
978
+ }
979
+ if (item["description"] !== undefined) {
980
+ const item_description = item["description"];
981
+ if (typeof item_description !== "string" ||
982
+ item_description.length < 1 ||
983
+ item_description.length > 240)
984
+ return "clinical_procedure_description";
985
+ }
986
+ if (item["performedDate"] !== undefined) {
987
+ const item_performedDate = item["performedDate"];
988
+ if (typeof item_performedDate !== "string" ||
989
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(item_performedDate) ||
990
+ !isIsoDate(item_performedDate))
991
+ return "clinical_procedure_performed_date";
992
+ }
993
+ }
994
+ }
995
+ if (value["medications"] !== undefined) {
996
+ const value_medications = value["medications"];
997
+ if (!Array.isArray(value_medications) || value_medications.length > 100)
998
+ return "clinical_medications";
999
+ for (const item of value_medications) {
1000
+ if (!isRecord(item))
1001
+ return "clinical_medication";
1002
+ if (!["medicationId"].every((key) => key in item))
1003
+ return "clinical_medication_keys";
1004
+ if (!Object.keys(item).every((key) => [
1005
+ "medicationId",
1006
+ "code",
1007
+ "codeSystem",
1008
+ "name",
1009
+ "dosage",
1010
+ "route",
1011
+ "administrationDate",
1012
+ ].includes(key)))
1013
+ return "clinical_medication_keys";
1014
+ const item_medicationId = item["medicationId"];
1015
+ if (typeof item_medicationId !== "string" ||
1016
+ item_medicationId.length < 1 ||
1017
+ item_medicationId.length > 60)
1018
+ return "clinical_medication_id";
1019
+ if (item["code"] !== undefined) {
1020
+ const item_code = item["code"];
1021
+ if (typeof item_code !== "string" ||
1022
+ item_code.length < 1 ||
1023
+ item_code.length > 64)
1024
+ return "clinical_medication_code";
1025
+ }
1026
+ if (item["codeSystem"] !== undefined) {
1027
+ const item_codeSystem = item["codeSystem"];
1028
+ if (typeof item_codeSystem !== "string" ||
1029
+ !["NDC", "RxNorm", "OTHER"].includes(item_codeSystem))
1030
+ return "clinical_medication_code_system";
1031
+ }
1032
+ if (item["name"] !== undefined) {
1033
+ const item_name = item["name"];
1034
+ if (typeof item_name !== "string" ||
1035
+ item_name.length < 1 ||
1036
+ item_name.length > 240)
1037
+ return "clinical_medication_name";
1038
+ }
1039
+ if (item["dosage"] !== undefined) {
1040
+ const item_dosage = item["dosage"];
1041
+ if (typeof item_dosage !== "string" ||
1042
+ item_dosage.length < 1 ||
1043
+ item_dosage.length > 120)
1044
+ return "clinical_medication_dosage";
1045
+ }
1046
+ if (item["route"] !== undefined) {
1047
+ const item_route = item["route"];
1048
+ if (typeof item_route !== "string" ||
1049
+ item_route.length < 1 ||
1050
+ item_route.length > 80)
1051
+ return "clinical_medication_route";
1052
+ }
1053
+ if (item["administrationDate"] !== undefined) {
1054
+ const item_administrationDate = item["administrationDate"];
1055
+ if (typeof item_administrationDate !== "string" ||
1056
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(item_administrationDate) ||
1057
+ !isIsoDate(item_administrationDate))
1058
+ return "clinical_medication_administration_date";
1059
+ }
1060
+ }
1061
+ }
1062
+ if (value["supplies"] !== undefined) {
1063
+ const value_supplies = value["supplies"];
1064
+ if (!Array.isArray(value_supplies) || value_supplies.length > 100)
1065
+ return "clinical_supplies";
1066
+ for (const item of value_supplies) {
1067
+ if (!isRecord(item))
1068
+ return "clinical_supply";
1069
+ if (!["supplyId"].every((key) => key in item))
1070
+ return "clinical_supply_keys";
1071
+ if (!Object.keys(item).every((key) => [
1072
+ "supplyId",
1073
+ "code",
1074
+ "codeSystem",
1075
+ "name",
1076
+ "quantity",
1077
+ "unitOfMeasure",
1078
+ "supplyDate",
1079
+ ].includes(key)))
1080
+ return "clinical_supply_keys";
1081
+ const item_supplyId = item["supplyId"];
1082
+ if (typeof item_supplyId !== "string" ||
1083
+ item_supplyId.length < 1 ||
1084
+ item_supplyId.length > 60)
1085
+ return "clinical_supply_id";
1086
+ if (item["code"] !== undefined) {
1087
+ const item_code = item["code"];
1088
+ if (typeof item_code !== "string" ||
1089
+ item_code.length < 1 ||
1090
+ item_code.length > 64)
1091
+ return "clinical_supply_code";
1092
+ }
1093
+ if (item["codeSystem"] !== undefined) {
1094
+ const item_codeSystem = item["codeSystem"];
1095
+ if (typeof item_codeSystem !== "string" ||
1096
+ !["HCPCS", "NDC", "OTHER"].includes(item_codeSystem))
1097
+ return "clinical_supply_code_system";
1098
+ }
1099
+ if (item["name"] !== undefined) {
1100
+ const item_name = item["name"];
1101
+ if (typeof item_name !== "string" ||
1102
+ item_name.length < 1 ||
1103
+ item_name.length > 240)
1104
+ return "clinical_supply_name";
1105
+ }
1106
+ if (item["quantity"] !== undefined) {
1107
+ const item_quantity = item["quantity"];
1108
+ if (typeof item_quantity !== "number" ||
1109
+ Number.isNaN(item_quantity) ||
1110
+ !Number.isInteger(item_quantity) ||
1111
+ item_quantity < 0 ||
1112
+ item_quantity > 999999)
1113
+ return "clinical_supply_quantity";
1114
+ }
1115
+ if (item["unitOfMeasure"] !== undefined) {
1116
+ const item_unitOfMeasure = item["unitOfMeasure"];
1117
+ if (typeof item_unitOfMeasure !== "string" ||
1118
+ item_unitOfMeasure.length < 1 ||
1119
+ item_unitOfMeasure.length > 20)
1120
+ return "clinical_supply_unit_of_measure";
1121
+ }
1122
+ if (item["supplyDate"] !== undefined) {
1123
+ const item_supplyDate = item["supplyDate"];
1124
+ if (typeof item_supplyDate !== "string" ||
1125
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(item_supplyDate) ||
1126
+ !isIsoDate(item_supplyDate))
1127
+ return "clinical_supply_date";
1128
+ }
1129
+ }
1130
+ }
1131
+ if (value["timeUnits"] !== undefined) {
1132
+ const value_timeUnits = value["timeUnits"];
1133
+ if (!Array.isArray(value_timeUnits) || value_timeUnits.length > 200)
1134
+ return "clinical_time_units";
1135
+ for (const item of value_timeUnits) {
1136
+ if (!isRecord(item))
1137
+ return "clinical_time_unit";
1138
+ if (!["timeId", "date", "durationMinutes"].every((key) => key in item))
1139
+ return "clinical_time_unit_keys";
1140
+ if (!Object.keys(item).every((key) => [
1141
+ "timeId",
1142
+ "date",
1143
+ "durationMinutes",
1144
+ "activityCode",
1145
+ "activityDescription",
1146
+ "clinicianRole",
1147
+ "placeOfService",
1148
+ ].includes(key)))
1149
+ return "clinical_time_unit_keys";
1150
+ const item_timeId = item["timeId"];
1151
+ if (typeof item_timeId !== "string" ||
1152
+ item_timeId.length < 1 ||
1153
+ item_timeId.length > 60)
1154
+ return "clinical_time_unit_id";
1155
+ const item_date = item["date"];
1156
+ if (typeof item_date !== "string" ||
1157
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(item_date) ||
1158
+ !isIsoDate(item_date))
1159
+ return "clinical_time_unit_date";
1160
+ const item_durationMinutes = item["durationMinutes"];
1161
+ if (typeof item_durationMinutes !== "number" ||
1162
+ Number.isNaN(item_durationMinutes) ||
1163
+ !Number.isInteger(item_durationMinutes) ||
1164
+ item_durationMinutes < 1 ||
1165
+ item_durationMinutes > 1440)
1166
+ return "clinical_time_unit_duration";
1167
+ if (item["activityCode"] !== undefined) {
1168
+ const item_activityCode = item["activityCode"];
1169
+ if (typeof item_activityCode !== "string" ||
1170
+ item_activityCode.length < 1 ||
1171
+ item_activityCode.length > 80)
1172
+ return "clinical_time_unit_activity_code";
1173
+ }
1174
+ if (item["activityDescription"] !== undefined) {
1175
+ const item_activityDescription = item["activityDescription"];
1176
+ if (typeof item_activityDescription !== "string" ||
1177
+ item_activityDescription.length < 1 ||
1178
+ item_activityDescription.length > 240)
1179
+ return "clinical_time_unit_activity_description";
1180
+ }
1181
+ if (item["clinicianRole"] !== undefined) {
1182
+ const item_clinicianRole = item["clinicianRole"];
1183
+ if (typeof item_clinicianRole !== "string" ||
1184
+ ![
1185
+ "attending",
1186
+ "physician",
1187
+ "nurse_practitioner",
1188
+ "physician_assistant",
1189
+ "resident",
1190
+ "other",
1191
+ ].includes(item_clinicianRole))
1192
+ return "clinical_time_unit_clinician_role";
1193
+ }
1194
+ if (item["placeOfService"] !== undefined) {
1195
+ const item_placeOfService = item["placeOfService"];
1196
+ if (typeof item_placeOfService !== "string" ||
1197
+ !new RegExp("^[0-9]{2}$").test(item_placeOfService))
1198
+ return "clinical_time_unit_place_of_service";
1199
+ }
1200
+ }
1201
+ }
1202
+ if (value["notes"] !== undefined) {
1203
+ const value_notes = value["notes"];
1204
+ if (!Array.isArray(value_notes) || value_notes.length > 50)
1205
+ return "clinical_notes";
1206
+ for (const item of value_notes) {
1207
+ if (!isRecord(item))
1208
+ return "clinical_note";
1209
+ if (!["noteId", "noteType", "note"].every((key) => key in item))
1210
+ return "clinical_note_keys";
1211
+ if (!Object.keys(item).every((key) => ["noteId", "noteType", "note"].includes(key)))
1212
+ return "clinical_note_keys";
1213
+ const item_noteId = item["noteId"];
1214
+ if (typeof item_noteId !== "string" ||
1215
+ item_noteId.length < 1 ||
1216
+ item_noteId.length > 60)
1217
+ return "clinical_note_id";
1218
+ const item_noteType = item["noteType"];
1219
+ if (typeof item_noteType !== "string" ||
1220
+ ![
1221
+ "clinical_narrative",
1222
+ "procedure_narrative",
1223
+ "authorization",
1224
+ "correspondence",
1225
+ "other",
1226
+ ].includes(item_noteType))
1227
+ return "clinical_note_type";
1228
+ const item_note = item["note"];
1229
+ if (typeof item_note !== "string" ||
1230
+ item_note.length < 1 ||
1231
+ item_note.length > 10000 ||
1232
+ item_note.trim().length === 0)
1233
+ return "clinical_note_text";
1234
+ }
1235
+ }
1236
+ if (value["sourceReferences"] !== undefined) {
1237
+ const value_sourceReferences = value["sourceReferences"];
1238
+ if (!Array.isArray(value_sourceReferences) ||
1239
+ value_sourceReferences.length > 50)
1240
+ return "clinical_source_references";
1241
+ for (const item of value_sourceReferences) {
1242
+ if (!isRecord(item))
1243
+ return "clinical_source_reference";
1244
+ if (!["sourceId", "sourceLabel"].every((key) => key in item))
1245
+ return "clinical_source_reference_keys";
1246
+ if (!Object.keys(item).every((key) => [
1247
+ "sourceId",
1248
+ "sourceLabel",
1249
+ "documentId",
1250
+ "excerpt",
1251
+ "sourceVersion",
1252
+ "corpusScope",
1253
+ "publisher",
1254
+ "effectiveDate",
1255
+ "retrievalDate",
1256
+ "coveredPayerProgram",
1257
+ "sourceUrl",
1258
+ "documentHash",
1259
+ "capturedAt",
1260
+ "humanReviewRequired",
1261
+ ].includes(key)))
1262
+ return "clinical_source_reference_keys";
1263
+ const item_sourceId = item["sourceId"];
1264
+ if (typeof item_sourceId !== "string" ||
1265
+ item_sourceId.length < 1 ||
1266
+ item_sourceId.length > 60)
1267
+ return "clinical_source_reference_id";
1268
+ const item_sourceLabel = item["sourceLabel"];
1269
+ if (typeof item_sourceLabel !== "string" ||
1270
+ item_sourceLabel.length < 1 ||
1271
+ item_sourceLabel.length > 120)
1272
+ return "clinical_source_reference_label";
1273
+ if (item["documentId"] !== undefined) {
1274
+ const item_documentId = item["documentId"];
1275
+ if (typeof item_documentId !== "string" ||
1276
+ item_documentId.length < 1 ||
1277
+ item_documentId.length > 240)
1278
+ return "clinical_source_reference_document_id";
1279
+ }
1280
+ if (item["excerpt"] !== undefined) {
1281
+ const item_excerpt = item["excerpt"];
1282
+ if (typeof item_excerpt !== "string" ||
1283
+ item_excerpt.length < 1 ||
1284
+ item_excerpt.length > 2000 ||
1285
+ item_excerpt.trim().length === 0)
1286
+ return "clinical_source_reference_excerpt";
1287
+ }
1288
+ if (item["sourceVersion"] !== undefined) {
1289
+ const item_sourceVersion = item["sourceVersion"];
1290
+ if (typeof item_sourceVersion !== "string" ||
1291
+ item_sourceVersion.length < 1 ||
1292
+ item_sourceVersion.length > 80)
1293
+ return "clinical_source_reference_version";
1294
+ }
1295
+ if (item["corpusScope"] !== undefined) {
1296
+ const item_corpusScope = item["corpusScope"];
1297
+ if (typeof item_corpusScope !== "string" ||
1298
+ !["base", "tenant"].includes(item_corpusScope))
1299
+ return "clinical_source_reference_corpus_scope";
1300
+ }
1301
+ if (item["publisher"] !== undefined) {
1302
+ const item_publisher = item["publisher"];
1303
+ if (typeof item_publisher !== "string" ||
1304
+ item_publisher.length < 1 ||
1305
+ item_publisher.length > 240)
1306
+ return "clinical_source_reference_publisher";
1307
+ }
1308
+ if (item["effectiveDate"] !== undefined) {
1309
+ const item_effectiveDate = item["effectiveDate"];
1310
+ if (typeof item_effectiveDate !== "string" ||
1311
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(item_effectiveDate) ||
1312
+ !isIsoDate(item_effectiveDate))
1313
+ return "clinical_source_reference_effective_date";
1314
+ }
1315
+ if (item["retrievalDate"] !== undefined) {
1316
+ const item_retrievalDate = item["retrievalDate"];
1317
+ if (typeof item_retrievalDate !== "string" ||
1318
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(item_retrievalDate) ||
1319
+ !isIsoDate(item_retrievalDate))
1320
+ return "clinical_source_reference_retrieval_date";
1321
+ }
1322
+ if (item["coveredPayerProgram"] !== undefined) {
1323
+ const item_coveredPayerProgram = item["coveredPayerProgram"];
1324
+ if (typeof item_coveredPayerProgram !== "string" ||
1325
+ item_coveredPayerProgram.length < 1 ||
1326
+ item_coveredPayerProgram.length > 240)
1327
+ return "clinical_source_reference_covered_payer_program";
1328
+ }
1329
+ if (item["sourceUrl"] !== undefined) {
1330
+ const item_sourceUrl = item["sourceUrl"];
1331
+ if (typeof item_sourceUrl !== "string" ||
1332
+ item_sourceUrl.length < 1 ||
1333
+ item_sourceUrl.length > 2048)
1334
+ return "clinical_source_reference_url";
1335
+ }
1336
+ if (item["documentHash"] !== undefined) {
1337
+ const item_documentHash = item["documentHash"];
1338
+ if (typeof item_documentHash !== "string" ||
1339
+ item_documentHash.length < 1 ||
1340
+ item_documentHash.length > 64)
1341
+ return "clinical_source_reference_hash";
1342
+ }
1343
+ if (item["capturedAt"] !== undefined) {
1344
+ const item_capturedAt = item["capturedAt"];
1345
+ if (typeof item_capturedAt !== "string" ||
1346
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(item_capturedAt) ||
1347
+ !isIsoDate(item_capturedAt))
1348
+ return "clinical_source_reference_captured_at";
1349
+ }
1350
+ if (item["humanReviewRequired"] !== undefined) {
1351
+ const item_humanReviewRequired = item["humanReviewRequired"];
1352
+ if (typeof item_humanReviewRequired !== "boolean" ||
1353
+ item_humanReviewRequired !== true)
1354
+ return "clinical_source_reference_human_review_required";
1355
+ }
1356
+ }
1357
+ }
1358
+ return null;
1359
+ }
1360
+ const validCodingCaseClinical = (value) => codingCaseClinicalValidationError(value) === null;
1361
+ exports.validCodingCaseClinical = validCodingCaseClinical;
1362
+ exports.CodingCaseClinicalSchemaJson = {
1363
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1364
+ $id: "https://nexalink.care/contracts/coding-case-clinical.schema.json",
1365
+ title: "CodingCaseClinical",
1366
+ description: "Structured clinical and operational facts: diagnoses, procedures, medications, supplies, time entries, notes, and source references. Time entries keep duration and activity structured so workflows such as monthly multi-activity time aggregation never depend on free text for calculations.",
1367
+ version: "1.0.0",
1368
+ type: "object",
1369
+ additionalProperties: false,
1370
+ properties: {
1371
+ diagnoses: {
1372
+ type: "array",
1373
+ maxItems: 100,
1374
+ items: {
1375
+ type: "object",
1376
+ additionalProperties: false,
1377
+ required: ["diagnosisId"],
1378
+ properties: {
1379
+ diagnosisId: {
1380
+ type: "string",
1381
+ minLength: 1,
1382
+ maxLength: 60,
1383
+ },
1384
+ code: {
1385
+ type: "string",
1386
+ minLength: 1,
1387
+ maxLength: 32,
1388
+ },
1389
+ codeSystem: {
1390
+ type: "string",
1391
+ enum: ["ICD-10-CM", "ICD-9-CM", "OTHER"],
1392
+ },
1393
+ codeVersion: {
1394
+ type: "string",
1395
+ minLength: 1,
1396
+ maxLength: 40,
1397
+ },
1398
+ description: {
1399
+ type: "string",
1400
+ minLength: 1,
1401
+ maxLength: 240,
1402
+ },
1403
+ diagnosisType: {
1404
+ type: "string",
1405
+ enum: ["principal", "secondary", "complication", "other"],
1406
+ },
1407
+ onsetDate: {
1408
+ type: "string",
1409
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
1410
+ format: "date",
1411
+ },
1412
+ presentOnAdmission: {
1413
+ type: "boolean",
1414
+ },
1415
+ },
1416
+ },
1417
+ },
1418
+ procedures: {
1419
+ type: "array",
1420
+ maxItems: 100,
1421
+ items: {
1422
+ type: "object",
1423
+ additionalProperties: false,
1424
+ required: ["procedureId"],
1425
+ properties: {
1426
+ procedureId: {
1427
+ type: "string",
1428
+ minLength: 1,
1429
+ maxLength: 60,
1430
+ },
1431
+ code: {
1432
+ type: "string",
1433
+ minLength: 1,
1434
+ maxLength: 64,
1435
+ },
1436
+ codeSystem: {
1437
+ type: "string",
1438
+ enum: ["CPT", "HCPCS", "ICD-10-PCS", "OTHER"],
1439
+ },
1440
+ codeVersion: {
1441
+ type: "string",
1442
+ minLength: 1,
1443
+ maxLength: 40,
1444
+ },
1445
+ description: {
1446
+ type: "string",
1447
+ minLength: 1,
1448
+ maxLength: 240,
1449
+ },
1450
+ performedDate: {
1451
+ type: "string",
1452
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
1453
+ format: "date",
1454
+ },
1455
+ },
1456
+ },
1457
+ },
1458
+ medications: {
1459
+ type: "array",
1460
+ maxItems: 100,
1461
+ items: {
1462
+ type: "object",
1463
+ additionalProperties: false,
1464
+ required: ["medicationId"],
1465
+ properties: {
1466
+ medicationId: {
1467
+ type: "string",
1468
+ minLength: 1,
1469
+ maxLength: 60,
1470
+ },
1471
+ code: {
1472
+ type: "string",
1473
+ minLength: 1,
1474
+ maxLength: 64,
1475
+ },
1476
+ codeSystem: {
1477
+ type: "string",
1478
+ enum: ["NDC", "RxNorm", "OTHER"],
1479
+ },
1480
+ name: {
1481
+ type: "string",
1482
+ minLength: 1,
1483
+ maxLength: 240,
1484
+ },
1485
+ dosage: {
1486
+ type: "string",
1487
+ minLength: 1,
1488
+ maxLength: 120,
1489
+ },
1490
+ route: {
1491
+ type: "string",
1492
+ minLength: 1,
1493
+ maxLength: 80,
1494
+ },
1495
+ administrationDate: {
1496
+ type: "string",
1497
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
1498
+ format: "date",
1499
+ },
1500
+ },
1501
+ },
1502
+ },
1503
+ supplies: {
1504
+ type: "array",
1505
+ maxItems: 100,
1506
+ items: {
1507
+ type: "object",
1508
+ additionalProperties: false,
1509
+ required: ["supplyId"],
1510
+ properties: {
1511
+ supplyId: {
1512
+ type: "string",
1513
+ minLength: 1,
1514
+ maxLength: 60,
1515
+ },
1516
+ code: {
1517
+ type: "string",
1518
+ minLength: 1,
1519
+ maxLength: 64,
1520
+ },
1521
+ codeSystem: {
1522
+ type: "string",
1523
+ enum: ["HCPCS", "NDC", "OTHER"],
1524
+ },
1525
+ name: {
1526
+ type: "string",
1527
+ minLength: 1,
1528
+ maxLength: 240,
1529
+ },
1530
+ quantity: {
1531
+ type: "integer",
1532
+ minimum: 0,
1533
+ maximum: 999999,
1534
+ },
1535
+ unitOfMeasure: {
1536
+ type: "string",
1537
+ minLength: 1,
1538
+ maxLength: 20,
1539
+ },
1540
+ supplyDate: {
1541
+ type: "string",
1542
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
1543
+ format: "date",
1544
+ },
1545
+ },
1546
+ },
1547
+ },
1548
+ timeUnits: {
1549
+ type: "array",
1550
+ maxItems: 200,
1551
+ items: {
1552
+ type: "object",
1553
+ additionalProperties: false,
1554
+ required: ["timeId", "date", "durationMinutes"],
1555
+ properties: {
1556
+ timeId: {
1557
+ type: "string",
1558
+ minLength: 1,
1559
+ maxLength: 60,
1560
+ },
1561
+ date: {
1562
+ type: "string",
1563
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
1564
+ format: "date",
1565
+ },
1566
+ durationMinutes: {
1567
+ type: "integer",
1568
+ minimum: 1,
1569
+ maximum: 1440,
1570
+ },
1571
+ activityCode: {
1572
+ type: "string",
1573
+ minLength: 1,
1574
+ maxLength: 80,
1575
+ },
1576
+ activityDescription: {
1577
+ type: "string",
1578
+ minLength: 1,
1579
+ maxLength: 240,
1580
+ },
1581
+ clinicianRole: {
1582
+ type: "string",
1583
+ enum: [
1584
+ "attending",
1585
+ "physician",
1586
+ "nurse_practitioner",
1587
+ "physician_assistant",
1588
+ "resident",
1589
+ "other",
1590
+ ],
1591
+ },
1592
+ placeOfService: {
1593
+ type: "string",
1594
+ pattern: "^[0-9]{2}$",
1595
+ },
1596
+ },
1597
+ },
1598
+ },
1599
+ notes: {
1600
+ type: "array",
1601
+ maxItems: 50,
1602
+ items: {
1603
+ type: "object",
1604
+ additionalProperties: false,
1605
+ required: ["noteId", "noteType", "note"],
1606
+ properties: {
1607
+ noteId: {
1608
+ type: "string",
1609
+ minLength: 1,
1610
+ maxLength: 60,
1611
+ },
1612
+ noteType: {
1613
+ type: "string",
1614
+ enum: [
1615
+ "clinical_narrative",
1616
+ "procedure_narrative",
1617
+ "authorization",
1618
+ "correspondence",
1619
+ "other",
1620
+ ],
1621
+ },
1622
+ note: {
1623
+ type: "string",
1624
+ minLength: 1,
1625
+ maxLength: 10000,
1626
+ },
1627
+ },
1628
+ },
1629
+ },
1630
+ sourceReferences: {
1631
+ type: "array",
1632
+ maxItems: 50,
1633
+ items: {
1634
+ type: "object",
1635
+ additionalProperties: false,
1636
+ required: ["sourceId", "sourceLabel"],
1637
+ properties: {
1638
+ sourceId: {
1639
+ type: "string",
1640
+ minLength: 1,
1641
+ maxLength: 60,
1642
+ },
1643
+ sourceLabel: {
1644
+ type: "string",
1645
+ minLength: 1,
1646
+ maxLength: 120,
1647
+ },
1648
+ documentId: {
1649
+ type: "string",
1650
+ minLength: 1,
1651
+ maxLength: 240,
1652
+ },
1653
+ excerpt: {
1654
+ type: "string",
1655
+ minLength: 1,
1656
+ maxLength: 2000,
1657
+ },
1658
+ sourceVersion: {
1659
+ type: "string",
1660
+ minLength: 1,
1661
+ maxLength: 80,
1662
+ },
1663
+ corpusScope: {
1664
+ type: "string",
1665
+ enum: ["base", "tenant"],
1666
+ },
1667
+ publisher: {
1668
+ type: "string",
1669
+ minLength: 1,
1670
+ maxLength: 240,
1671
+ },
1672
+ effectiveDate: {
1673
+ type: "string",
1674
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
1675
+ format: "date",
1676
+ },
1677
+ retrievalDate: {
1678
+ type: "string",
1679
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
1680
+ format: "date",
1681
+ },
1682
+ coveredPayerProgram: {
1683
+ type: "string",
1684
+ minLength: 1,
1685
+ maxLength: 240,
1686
+ },
1687
+ sourceUrl: {
1688
+ type: "string",
1689
+ minLength: 1,
1690
+ maxLength: 2048,
1691
+ },
1692
+ documentHash: {
1693
+ type: "string",
1694
+ minLength: 1,
1695
+ maxLength: 64,
1696
+ },
1697
+ capturedAt: {
1698
+ type: "string",
1699
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
1700
+ format: "date",
1701
+ },
1702
+ humanReviewRequired: {
1703
+ type: "boolean",
1704
+ const: true,
1705
+ },
1706
+ },
1707
+ },
1708
+ },
1709
+ },
1710
+ };
1711
+ // --------------------------------------------------------------------
1712
+ // CodingServiceLine (schema 1.0.0, wire coding-service-line-v1)
1713
+ // --------------------------------------------------------------------
1714
+ exports.codingServiceLineSchema = zod_1.z
1715
+ .object({
1716
+ lineId: zod_1.z.string().min(1).max(60),
1717
+ submittedCode: zod_1.z
1718
+ .object({
1719
+ code: zod_1.z
1720
+ .string()
1721
+ .min(1)
1722
+ .max(64)
1723
+ .refine((value) => value.trim().length > 0),
1724
+ codeSystem: zod_1.z.enum([
1725
+ "ICD-10-CM",
1726
+ "ICD-10-PCS",
1727
+ "CPT",
1728
+ "HCPCS",
1729
+ "NDC",
1730
+ "CDT",
1731
+ "OTHER",
1732
+ ]),
1733
+ codeVersion: zod_1.z.string().min(1).max(40).optional(),
1734
+ })
1735
+ .strict(),
1736
+ modifiers: zod_1.z.array(zod_1.z.string().min(1).max(8)).max(8).optional(),
1737
+ units: zod_1.z
1738
+ .object({
1739
+ count: zod_1.z.number().int().min(0).max(999999).optional(),
1740
+ unitOfMeasure: zod_1.z.string().min(1).max(20).optional(),
1741
+ })
1742
+ .strict()
1743
+ .optional(),
1744
+ linkedDiagnoses: zod_1.z
1745
+ .array(zod_1.z
1746
+ .object({
1747
+ diagnosisRef: zod_1.z.string().min(1).max(60),
1748
+ sequence: zod_1.z.number().int().min(1).max(99).optional(),
1749
+ })
1750
+ .strict())
1751
+ .max(20)
1752
+ .optional(),
1753
+ serviceDate: zod_1.z
1754
+ .string()
1755
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
1756
+ .refine(isIsoDate)
1757
+ .optional(),
1758
+ })
1759
+ .strict();
1760
+ function codingServiceLineValidationError(value) {
1761
+ if (!isRecord(value))
1762
+ return "service_line";
1763
+ if (!["lineId", "submittedCode"].every((key) => key in value))
1764
+ return "service_line_keys";
1765
+ if (!Object.keys(value).every((key) => [
1766
+ "lineId",
1767
+ "submittedCode",
1768
+ "modifiers",
1769
+ "units",
1770
+ "linkedDiagnoses",
1771
+ "serviceDate",
1772
+ ].includes(key)))
1773
+ return "service_line_keys";
1774
+ const value_lineId = value["lineId"];
1775
+ if (typeof value_lineId !== "string" ||
1776
+ value_lineId.length < 1 ||
1777
+ value_lineId.length > 60)
1778
+ return "service_line_id";
1779
+ const value_submittedCode = value["submittedCode"];
1780
+ if (!isRecord(value_submittedCode))
1781
+ return "service_line_submitted_code";
1782
+ if (!["code", "codeSystem"].every((key) => key in value_submittedCode))
1783
+ return "service_line_submitted_code_keys";
1784
+ if (!Object.keys(value_submittedCode).every((key) => ["code", "codeSystem", "codeVersion"].includes(key)))
1785
+ return "service_line_submitted_code_keys";
1786
+ const value_submittedCode_code = value_submittedCode["code"];
1787
+ if (typeof value_submittedCode_code !== "string" ||
1788
+ value_submittedCode_code.length < 1 ||
1789
+ value_submittedCode_code.length > 64 ||
1790
+ value_submittedCode_code.trim().length === 0)
1791
+ return "service_line_code";
1792
+ const value_submittedCode_codeSystem = value_submittedCode["codeSystem"];
1793
+ if (typeof value_submittedCode_codeSystem !== "string" ||
1794
+ ![
1795
+ "ICD-10-CM",
1796
+ "ICD-10-PCS",
1797
+ "CPT",
1798
+ "HCPCS",
1799
+ "NDC",
1800
+ "CDT",
1801
+ "OTHER",
1802
+ ].includes(value_submittedCode_codeSystem))
1803
+ return "service_line_code_system";
1804
+ if (value_submittedCode["codeVersion"] !== undefined) {
1805
+ const value_submittedCode_codeVersion = value_submittedCode["codeVersion"];
1806
+ if (typeof value_submittedCode_codeVersion !== "string" ||
1807
+ value_submittedCode_codeVersion.length < 1 ||
1808
+ value_submittedCode_codeVersion.length > 40)
1809
+ return "service_line_code_version";
1810
+ }
1811
+ if (value["modifiers"] !== undefined) {
1812
+ const value_modifiers = value["modifiers"];
1813
+ if (!Array.isArray(value_modifiers) || value_modifiers.length > 8)
1814
+ return "service_line_modifiers";
1815
+ for (const item of value_modifiers) {
1816
+ if (typeof item !== "string" || item.length < 1 || item.length > 8)
1817
+ return "service_line_modifiers";
1818
+ }
1819
+ }
1820
+ if (value["units"] !== undefined) {
1821
+ const value_units = value["units"];
1822
+ if (!isRecord(value_units))
1823
+ return "service_line_units";
1824
+ if (!Object.keys(value_units).every((key) => ["count", "unitOfMeasure"].includes(key)))
1825
+ return "service_line_units_keys";
1826
+ if (value_units["count"] !== undefined) {
1827
+ const value_units_count = value_units["count"];
1828
+ if (typeof value_units_count !== "number" ||
1829
+ Number.isNaN(value_units_count) ||
1830
+ !Number.isInteger(value_units_count) ||
1831
+ value_units_count < 0 ||
1832
+ value_units_count > 999999)
1833
+ return "service_line_units_count";
1834
+ }
1835
+ if (value_units["unitOfMeasure"] !== undefined) {
1836
+ const value_units_unitOfMeasure = value_units["unitOfMeasure"];
1837
+ if (typeof value_units_unitOfMeasure !== "string" ||
1838
+ value_units_unitOfMeasure.length < 1 ||
1839
+ value_units_unitOfMeasure.length > 20)
1840
+ return "service_line_units_measure";
1841
+ }
1842
+ }
1843
+ if (value["linkedDiagnoses"] !== undefined) {
1844
+ const value_linkedDiagnoses = value["linkedDiagnoses"];
1845
+ if (!Array.isArray(value_linkedDiagnoses) ||
1846
+ value_linkedDiagnoses.length > 20)
1847
+ return "service_line_linked_diagnoses";
1848
+ for (const item of value_linkedDiagnoses) {
1849
+ if (!isRecord(item))
1850
+ return "service_line_linked_diagnosis";
1851
+ if (!["diagnosisRef"].every((key) => key in item))
1852
+ return "service_line_linked_diagnosis_keys";
1853
+ if (!Object.keys(item).every((key) => ["diagnosisRef", "sequence"].includes(key)))
1854
+ return "service_line_linked_diagnosis_keys";
1855
+ const item_diagnosisRef = item["diagnosisRef"];
1856
+ if (typeof item_diagnosisRef !== "string" ||
1857
+ item_diagnosisRef.length < 1 ||
1858
+ item_diagnosisRef.length > 60)
1859
+ return "service_line_diagnosis_ref";
1860
+ if (item["sequence"] !== undefined) {
1861
+ const item_sequence = item["sequence"];
1862
+ if (typeof item_sequence !== "number" ||
1863
+ Number.isNaN(item_sequence) ||
1864
+ !Number.isInteger(item_sequence) ||
1865
+ item_sequence < 1 ||
1866
+ item_sequence > 99)
1867
+ return "service_line_diagnosis_sequence";
1868
+ }
1869
+ }
1870
+ }
1871
+ if (value["serviceDate"] !== undefined) {
1872
+ const value_serviceDate = value["serviceDate"];
1873
+ if (typeof value_serviceDate !== "string" ||
1874
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(value_serviceDate) ||
1875
+ !isIsoDate(value_serviceDate))
1876
+ return "service_line_service_date";
1877
+ }
1878
+ return null;
1879
+ }
1880
+ const validCodingServiceLine = (value) => codingServiceLineValidationError(value) === null;
1881
+ exports.validCodingServiceLine = validCodingServiceLine;
1882
+ exports.CodingServiceLineSchemaJson = {
1883
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1884
+ $id: "https://nexalink.care/contracts/coding-service-line.schema.json",
1885
+ title: "CodingServiceLine",
1886
+ description: "One existing (submitted) claim line on a CodingCase. Decisions reference these lines by lineId; the line action is chosen by the decision, never stored here.",
1887
+ version: "1.0.0",
1888
+ type: "object",
1889
+ additionalProperties: false,
1890
+ required: ["lineId", "submittedCode"],
1891
+ properties: {
1892
+ lineId: {
1893
+ type: "string",
1894
+ minLength: 1,
1895
+ maxLength: 60,
1896
+ },
1897
+ submittedCode: {
1898
+ type: "object",
1899
+ additionalProperties: false,
1900
+ required: ["code", "codeSystem"],
1901
+ properties: {
1902
+ code: {
1903
+ type: "string",
1904
+ minLength: 1,
1905
+ maxLength: 64,
1906
+ },
1907
+ codeSystem: {
1908
+ type: "string",
1909
+ enum: [
1910
+ "ICD-10-CM",
1911
+ "ICD-10-PCS",
1912
+ "CPT",
1913
+ "HCPCS",
1914
+ "NDC",
1915
+ "CDT",
1916
+ "OTHER",
1917
+ ],
1918
+ },
1919
+ codeVersion: {
1920
+ type: "string",
1921
+ minLength: 1,
1922
+ maxLength: 40,
1923
+ },
1924
+ },
1925
+ },
1926
+ modifiers: {
1927
+ type: "array",
1928
+ maxItems: 8,
1929
+ items: {
1930
+ type: "string",
1931
+ minLength: 1,
1932
+ maxLength: 8,
1933
+ },
1934
+ },
1935
+ units: {
1936
+ type: "object",
1937
+ additionalProperties: false,
1938
+ properties: {
1939
+ count: {
1940
+ type: "integer",
1941
+ minimum: 0,
1942
+ maximum: 999999,
1943
+ },
1944
+ unitOfMeasure: {
1945
+ type: "string",
1946
+ minLength: 1,
1947
+ maxLength: 20,
1948
+ },
1949
+ },
1950
+ },
1951
+ linkedDiagnoses: {
1952
+ type: "array",
1953
+ maxItems: 20,
1954
+ items: {
1955
+ type: "object",
1956
+ additionalProperties: false,
1957
+ required: ["diagnosisRef"],
1958
+ properties: {
1959
+ diagnosisRef: {
1960
+ type: "string",
1961
+ minLength: 1,
1962
+ maxLength: 60,
1963
+ },
1964
+ sequence: {
1965
+ type: "integer",
1966
+ minimum: 1,
1967
+ maximum: 99,
1968
+ },
1969
+ },
1970
+ },
1971
+ },
1972
+ serviceDate: {
1973
+ type: "string",
1974
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
1975
+ format: "date",
1976
+ },
1977
+ },
1978
+ };
1979
+ // --------------------------------------------------------------------
1980
+ // CodingExtension (schema 1.0.0, wire coding-extension-v1)
1981
+ // --------------------------------------------------------------------
1982
+ exports.codingExtensionSchema = zod_1.z
1983
+ .object({
1984
+ namespace: zod_1.z
1985
+ .string()
1986
+ .regex(new RegExp("^[a-z0-9]+([._-][a-z0-9]+)*$"))
1987
+ .min(3)
1988
+ .max(160),
1989
+ schemaVersion: zod_1.z.string().min(1).max(40),
1990
+ payload: zod_1.z
1991
+ .object({})
1992
+ .passthrough()
1993
+ .refine((value) => Object.keys(value).length <= 50),
1994
+ })
1995
+ .strict();
1996
+ function codingExtensionValidationError(value) {
1997
+ if (!isRecord(value))
1998
+ return "extension";
1999
+ if (!["namespace", "schemaVersion", "payload"].every((key) => key in value))
2000
+ return "extension_keys";
2001
+ if (!Object.keys(value).every((key) => ["namespace", "schemaVersion", "payload"].includes(key)))
2002
+ return "extension_keys";
2003
+ const value_namespace = value["namespace"];
2004
+ if (typeof value_namespace !== "string" ||
2005
+ value_namespace.length < 3 ||
2006
+ value_namespace.length > 160 ||
2007
+ !new RegExp("^[a-z0-9]+([._-][a-z0-9]+)*$").test(value_namespace))
2008
+ return "extension_namespace";
2009
+ const value_schemaVersion = value["schemaVersion"];
2010
+ if (typeof value_schemaVersion !== "string" ||
2011
+ value_schemaVersion.length < 1 ||
2012
+ value_schemaVersion.length > 40)
2013
+ return "extension_schema_version";
2014
+ const value_payload = value["payload"];
2015
+ if (!isRecord(value_payload))
2016
+ return "extension_payload";
2017
+ if (Object.keys(value_payload).length > 50)
2018
+ return "extension_payload";
2019
+ return null;
2020
+ }
2021
+ const validCodingExtension = (value) => codingExtensionValidationError(value) === null;
2022
+ exports.validCodingExtension = validCodingExtension;
2023
+ exports.CodingExtensionSchemaJson = {
2024
+ $schema: "https://json-schema.org/draft/2020-12/schema",
2025
+ $id: "https://nexalink.care/contracts/coding-extension.schema.json",
2026
+ title: "CodingExtension",
2027
+ description: "A namespaced, bounded extension attached to a CodingCase or CodingDecision. Extensions carry pack-specific data without turning the shared envelope into an unbounded bag of specialty fields. Namespace ownership follows reverse-domain convention; Nexalink reserves com.nexalink and org.nexalink.",
2028
+ version: "1.0.0",
2029
+ type: "object",
2030
+ additionalProperties: false,
2031
+ required: ["namespace", "schemaVersion", "payload"],
2032
+ properties: {
2033
+ namespace: {
2034
+ type: "string",
2035
+ pattern: "^[a-z0-9]+([._-][a-z0-9]+)*$",
2036
+ minLength: 3,
2037
+ maxLength: 160,
2038
+ },
2039
+ schemaVersion: {
2040
+ type: "string",
2041
+ minLength: 1,
2042
+ maxLength: 40,
2043
+ },
2044
+ payload: {
2045
+ type: "object",
2046
+ maxProperties: 50,
2047
+ properties: {},
2048
+ },
2049
+ },
2050
+ };
2051
+ // --------------------------------------------------------------------
2052
+ // CodingCase (schema 1.0.0, wire coding-case-v1)
2053
+ // --------------------------------------------------------------------
2054
+ exports.codingCaseSchema = zod_1.z
2055
+ .object({
2056
+ caseId: zod_1.z.string().min(1).max(128),
2057
+ analyticsId: zod_1.z.string().min(1).max(128).optional(),
2058
+ tenantReference: zod_1.z.string().min(1).max(128).optional(),
2059
+ codingIntent: zod_1.z.enum([
2060
+ "encounter_review",
2061
+ "claim_review",
2062
+ "longitudinal_review",
2063
+ "monthly_time_aggregation",
2064
+ "batch_review",
2065
+ ]),
2066
+ servicePeriod: zod_1.z
2067
+ .object({
2068
+ startDate: zod_1.z
2069
+ .string()
2070
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
2071
+ .refine(isIsoDate),
2072
+ endDate: zod_1.z
2073
+ .string()
2074
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
2075
+ .refine(isIsoDate)
2076
+ .optional(),
2077
+ })
2078
+ .strict(),
2079
+ context: exports.codingCaseContextSchema,
2080
+ payer: exports.codingCasePayerSchema.optional(),
2081
+ clinical: exports.codingCaseClinicalSchema,
2082
+ submittedClaimLines: zod_1.z.array(exports.codingServiceLineSchema).max(100).optional(),
2083
+ extensions: zod_1.z.array(exports.codingExtensionSchema).max(25).optional(),
2084
+ })
2085
+ .strict();
2086
+ function codingCaseValidationError(value) {
2087
+ if (!isRecord(value))
2088
+ return "coding_case";
2089
+ if (!["caseId", "codingIntent", "servicePeriod", "context", "clinical"].every((key) => key in value))
2090
+ return "coding_case_keys";
2091
+ if (!Object.keys(value).every((key) => [
2092
+ "caseId",
2093
+ "analyticsId",
2094
+ "tenantReference",
2095
+ "codingIntent",
2096
+ "servicePeriod",
2097
+ "context",
2098
+ "payer",
2099
+ "clinical",
2100
+ "submittedClaimLines",
2101
+ "extensions",
2102
+ ].includes(key)))
2103
+ return "coding_case_keys";
2104
+ const value_caseId = value["caseId"];
2105
+ if (typeof value_caseId !== "string" ||
2106
+ value_caseId.length < 1 ||
2107
+ value_caseId.length > 128)
2108
+ return "case_id";
2109
+ if (value["analyticsId"] !== undefined) {
2110
+ const value_analyticsId = value["analyticsId"];
2111
+ if (typeof value_analyticsId !== "string" ||
2112
+ value_analyticsId.length < 1 ||
2113
+ value_analyticsId.length > 128)
2114
+ return "case_analytics_id";
2115
+ }
2116
+ if (value["tenantReference"] !== undefined) {
2117
+ const value_tenantReference = value["tenantReference"];
2118
+ if (typeof value_tenantReference !== "string" ||
2119
+ value_tenantReference.length < 1 ||
2120
+ value_tenantReference.length > 128)
2121
+ return "case_tenant_reference";
2122
+ }
2123
+ const value_codingIntent = value["codingIntent"];
2124
+ if (typeof value_codingIntent !== "string" ||
2125
+ ![
2126
+ "encounter_review",
2127
+ "claim_review",
2128
+ "longitudinal_review",
2129
+ "monthly_time_aggregation",
2130
+ "batch_review",
2131
+ ].includes(value_codingIntent))
2132
+ return "case_coding_intent";
2133
+ const value_servicePeriod = value["servicePeriod"];
2134
+ if (!isRecord(value_servicePeriod))
2135
+ return "case_service_period";
2136
+ if (!["startDate"].every((key) => key in value_servicePeriod))
2137
+ return "case_service_period_keys";
2138
+ if (!Object.keys(value_servicePeriod).every((key) => ["startDate", "endDate"].includes(key)))
2139
+ return "case_service_period_keys";
2140
+ const value_servicePeriod_startDate = value_servicePeriod["startDate"];
2141
+ if (typeof value_servicePeriod_startDate !== "string" ||
2142
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(value_servicePeriod_startDate) ||
2143
+ !isIsoDate(value_servicePeriod_startDate))
2144
+ return "case_service_period_start";
2145
+ if (value_servicePeriod["endDate"] !== undefined) {
2146
+ const value_servicePeriod_endDate = value_servicePeriod["endDate"];
2147
+ if (typeof value_servicePeriod_endDate !== "string" ||
2148
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(value_servicePeriod_endDate) ||
2149
+ !isIsoDate(value_servicePeriod_endDate))
2150
+ return "case_service_period_end";
2151
+ }
2152
+ const value_context = value["context"];
2153
+ const value_contextRefError = codingCaseContextValidationError(value_context);
2154
+ if (value_contextRefError !== null)
2155
+ return value_contextRefError;
2156
+ if (value["payer"] !== undefined) {
2157
+ const value_payer = value["payer"];
2158
+ const value_payerRefError = codingCasePayerValidationError(value_payer);
2159
+ if (value_payerRefError !== null)
2160
+ return value_payerRefError;
2161
+ }
2162
+ const value_clinical = value["clinical"];
2163
+ const value_clinicalRefError = codingCaseClinicalValidationError(value_clinical);
2164
+ if (value_clinicalRefError !== null)
2165
+ return value_clinicalRefError;
2166
+ if (value["submittedClaimLines"] !== undefined) {
2167
+ const value_submittedClaimLines = value["submittedClaimLines"];
2168
+ if (!Array.isArray(value_submittedClaimLines) ||
2169
+ value_submittedClaimLines.length > 100)
2170
+ return "case_submitted_claim_lines";
2171
+ for (const item of value_submittedClaimLines) {
2172
+ const itemRefError = codingServiceLineValidationError(item);
2173
+ if (itemRefError !== null)
2174
+ return itemRefError;
2175
+ }
2176
+ }
2177
+ if (value["extensions"] !== undefined) {
2178
+ const value_extensions = value["extensions"];
2179
+ if (!Array.isArray(value_extensions) || value_extensions.length > 25)
2180
+ return "case_extensions";
2181
+ for (const item of value_extensions) {
2182
+ const itemRefError = codingExtensionValidationError(item);
2183
+ if (itemRefError !== null)
2184
+ return itemRefError;
2185
+ }
2186
+ }
2187
+ return null;
2188
+ }
2189
+ const validCodingCase = (value) => codingCaseValidationError(value) === null;
2190
+ exports.validCodingCase = validCodingCase;
2191
+ exports.CodingCaseSchemaJson = {
2192
+ $schema: "https://json-schema.org/draft/2020-12/schema",
2193
+ $id: "https://nexalink.care/contracts/coding-case.schema.json",
2194
+ title: "CodingCase",
2195
+ description: "The canonical case envelope for encounter, claim-review, longitudinal, monthly time aggregation, and batch coding workflows. caseId is a client-supplied direct reference; analyticsId is the separate analytics-safe identifier that may be referenced by decisions and metrics without exposing case identity.",
2196
+ version: "1.0.0",
2197
+ type: "object",
2198
+ additionalProperties: false,
2199
+ required: ["caseId", "codingIntent", "servicePeriod", "context", "clinical"],
2200
+ properties: {
2201
+ caseId: {
2202
+ type: "string",
2203
+ minLength: 1,
2204
+ maxLength: 128,
2205
+ },
2206
+ analyticsId: {
2207
+ type: "string",
2208
+ minLength: 1,
2209
+ maxLength: 128,
2210
+ },
2211
+ tenantReference: {
2212
+ type: "string",
2213
+ minLength: 1,
2214
+ maxLength: 128,
2215
+ },
2216
+ codingIntent: {
2217
+ type: "string",
2218
+ enum: [
2219
+ "encounter_review",
2220
+ "claim_review",
2221
+ "longitudinal_review",
2222
+ "monthly_time_aggregation",
2223
+ "batch_review",
2224
+ ],
2225
+ },
2226
+ servicePeriod: {
2227
+ type: "object",
2228
+ additionalProperties: false,
2229
+ required: ["startDate"],
2230
+ properties: {
2231
+ startDate: {
2232
+ type: "string",
2233
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
2234
+ format: "date",
2235
+ },
2236
+ endDate: {
2237
+ type: "string",
2238
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
2239
+ format: "date",
2240
+ },
2241
+ },
2242
+ },
2243
+ context: {
2244
+ $ref: "coding-case-context.schema.json",
2245
+ },
2246
+ payer: {
2247
+ $ref: "coding-case-payer.schema.json",
2248
+ },
2249
+ clinical: {
2250
+ $ref: "coding-case-clinical.schema.json",
2251
+ },
2252
+ submittedClaimLines: {
2253
+ type: "array",
2254
+ maxItems: 100,
2255
+ items: {
2256
+ $ref: "coding-service-line.schema.json",
2257
+ },
2258
+ },
2259
+ extensions: {
2260
+ type: "array",
2261
+ maxItems: 25,
2262
+ items: {
2263
+ $ref: "coding-extension.schema.json",
2264
+ },
2265
+ },
2266
+ },
2267
+ };
2268
+ // --------------------------------------------------------------------
2269
+ // CodingBatch (schema 1.0.0, wire coding-batch-v1)
2270
+ // --------------------------------------------------------------------
2271
+ exports.codingBatchSchema = zod_1.z
2272
+ .object({
2273
+ batchId: zod_1.z.string().min(1).max(128),
2274
+ tenantReference: zod_1.z.string().min(1).max(128).optional(),
2275
+ intent: zod_1.z.literal("batch_review"),
2276
+ cases: zod_1.z.array(exports.codingCaseSchema).min(1).max(100),
2277
+ createdBy: zod_1.z.string().min(1).max(128).optional(),
2278
+ createdAt: zod_1.z
2279
+ .string()
2280
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$"))
2281
+ .refine(isRfc3339DateTime)
2282
+ .max(64),
2283
+ extensions: zod_1.z.array(exports.codingExtensionSchema).max(25).optional(),
2284
+ })
2285
+ .strict();
2286
+ function codingBatchValidationError(value) {
2287
+ if (!isRecord(value))
2288
+ return "coding_batch";
2289
+ if (!["batchId", "intent", "cases", "createdAt"].every((key) => key in value))
2290
+ return "coding_batch_keys";
2291
+ if (!Object.keys(value).every((key) => [
2292
+ "batchId",
2293
+ "tenantReference",
2294
+ "intent",
2295
+ "cases",
2296
+ "createdBy",
2297
+ "createdAt",
2298
+ "extensions",
2299
+ ].includes(key)))
2300
+ return "coding_batch_keys";
2301
+ const value_batchId = value["batchId"];
2302
+ if (typeof value_batchId !== "string" ||
2303
+ value_batchId.length < 1 ||
2304
+ value_batchId.length > 128)
2305
+ return "batch_id";
2306
+ if (value["tenantReference"] !== undefined) {
2307
+ const value_tenantReference = value["tenantReference"];
2308
+ if (typeof value_tenantReference !== "string" ||
2309
+ value_tenantReference.length < 1 ||
2310
+ value_tenantReference.length > 128)
2311
+ return "batch_tenant_reference";
2312
+ }
2313
+ const value_intent = value["intent"];
2314
+ if (typeof value_intent !== "string" || value_intent !== "batch_review")
2315
+ return "batch_intent";
2316
+ const value_cases = value["cases"];
2317
+ if (!Array.isArray(value_cases) ||
2318
+ value_cases.length < 1 ||
2319
+ value_cases.length > 100)
2320
+ return "batch_cases";
2321
+ for (const item of value_cases) {
2322
+ const itemRefError = codingCaseValidationError(item);
2323
+ if (itemRefError !== null)
2324
+ return itemRefError;
2325
+ }
2326
+ if (value["createdBy"] !== undefined) {
2327
+ const value_createdBy = value["createdBy"];
2328
+ if (typeof value_createdBy !== "string" ||
2329
+ value_createdBy.length < 1 ||
2330
+ value_createdBy.length > 128)
2331
+ return "batch_created_by";
2332
+ }
2333
+ const value_createdAt = value["createdAt"];
2334
+ if (typeof value_createdAt !== "string" ||
2335
+ value_createdAt.length > 64 ||
2336
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$").test(value_createdAt) ||
2337
+ !isRfc3339DateTime(value_createdAt))
2338
+ return "batch_created_at";
2339
+ if (value["extensions"] !== undefined) {
2340
+ const value_extensions = value["extensions"];
2341
+ if (!Array.isArray(value_extensions) || value_extensions.length > 25)
2342
+ return "batch_extensions";
2343
+ for (const item of value_extensions) {
2344
+ const itemRefError = codingExtensionValidationError(item);
2345
+ if (itemRefError !== null)
2346
+ return itemRefError;
2347
+ }
2348
+ }
2349
+ return null;
2350
+ }
2351
+ const validCodingBatch = (value) => codingBatchValidationError(value) === null;
2352
+ exports.validCodingBatch = validCodingBatch;
2353
+ exports.CodingBatchSchemaJson = {
2354
+ $schema: "https://json-schema.org/draft/2020-12/schema",
2355
+ $id: "https://nexalink.care/contracts/coding-batch.schema.json",
2356
+ title: "CodingBatch",
2357
+ description: "A bounded batch envelope carrying CodingCase instances for batch review. Batch size is capped so one execution remains within runtime limits; unbounded or streaming workloads are out of scope for this envelope.",
2358
+ version: "1.0.0",
2359
+ type: "object",
2360
+ additionalProperties: false,
2361
+ required: ["batchId", "intent", "cases", "createdAt"],
2362
+ properties: {
2363
+ batchId: {
2364
+ type: "string",
2365
+ minLength: 1,
2366
+ maxLength: 128,
2367
+ },
2368
+ tenantReference: {
2369
+ type: "string",
2370
+ minLength: 1,
2371
+ maxLength: 128,
2372
+ },
2373
+ intent: {
2374
+ type: "string",
2375
+ const: "batch_review",
2376
+ },
2377
+ cases: {
2378
+ type: "array",
2379
+ minItems: 1,
2380
+ maxItems: 100,
2381
+ items: {
2382
+ $ref: "coding-case.schema.json",
2383
+ },
2384
+ },
2385
+ createdBy: {
2386
+ type: "string",
2387
+ minLength: 1,
2388
+ maxLength: 128,
2389
+ },
2390
+ createdAt: {
2391
+ type: "string",
2392
+ pattern: "^\\d{4}-\\d{2}-\\d{2}T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$",
2393
+ format: "date-time",
2394
+ maxLength: 64,
2395
+ },
2396
+ extensions: {
2397
+ type: "array",
2398
+ maxItems: 25,
2399
+ items: {
2400
+ $ref: "coding-extension.schema.json",
2401
+ },
2402
+ },
2403
+ },
2404
+ };
2405
+ // --------------------------------------------------------------------
2406
+ // CodingDecisionLine (schema 1.0.0, wire coding-decision-line-v1)
2407
+ // --------------------------------------------------------------------
2408
+ exports.codingDecisionLineSchema = zod_1.z
2409
+ .object({
2410
+ lineId: zod_1.z.string().min(1).max(60),
2411
+ action: zod_1.z.enum(["add", "retain", "replace", "remove", "review"]),
2412
+ code: zod_1.z
2413
+ .object({
2414
+ code: zod_1.z
2415
+ .string()
2416
+ .min(1)
2417
+ .max(64)
2418
+ .refine((value) => value.trim().length > 0),
2419
+ codeSystem: zod_1.z.enum([
2420
+ "ICD-10-CM",
2421
+ "ICD-10-PCS",
2422
+ "CPT",
2423
+ "HCPCS",
2424
+ "NDC",
2425
+ "CDT",
2426
+ "REVENUE_CODE",
2427
+ "DRG",
2428
+ "OTHER",
2429
+ ]),
2430
+ codeVersion: zod_1.z.string().min(1).max(40).optional(),
2431
+ })
2432
+ .strict(),
2433
+ modifiers: zod_1.z.array(zod_1.z.string().min(1).max(8)).max(8).optional(),
2434
+ units: zod_1.z
2435
+ .object({
2436
+ count: zod_1.z.number().int().min(0).max(999999).optional(),
2437
+ unitOfMeasure: zod_1.z.string().min(1).max(20).optional(),
2438
+ })
2439
+ .strict()
2440
+ .optional(),
2441
+ linkedDiagnoses: zod_1.z
2442
+ .array(zod_1.z
2443
+ .object({
2444
+ diagnosisRef: zod_1.z.string().min(1).max(60),
2445
+ sequence: zod_1.z.number().int().min(1).max(99).optional(),
2446
+ })
2447
+ .strict())
2448
+ .max(20)
2449
+ .optional(),
2450
+ sequence: zod_1.z.number().int().min(1).max(999).optional(),
2451
+ confidence: zod_1.z.enum(["low", "medium", "high"]),
2452
+ rationale: zod_1.z
2453
+ .string()
2454
+ .min(1)
2455
+ .max(2000)
2456
+ .refine((value) => value.trim().length > 0),
2457
+ evidenceRefs: zod_1.z.array(zod_1.z.string().min(1).max(64)).max(10).optional(),
2458
+ gapRefs: zod_1.z.array(zod_1.z.string().min(1).max(64)).max(10).optional(),
2459
+ conflictRefs: zod_1.z.array(zod_1.z.string().min(1).max(64)).max(10).optional(),
2460
+ })
2461
+ .strict();
2462
+ function codingDecisionLineValidationError(value) {
2463
+ if (!isRecord(value))
2464
+ return "decision_line";
2465
+ if (!["lineId", "action", "code", "confidence", "rationale"].every((key) => key in value))
2466
+ return "decision_line_keys";
2467
+ if (!Object.keys(value).every((key) => [
2468
+ "lineId",
2469
+ "action",
2470
+ "code",
2471
+ "modifiers",
2472
+ "units",
2473
+ "linkedDiagnoses",
2474
+ "sequence",
2475
+ "confidence",
2476
+ "rationale",
2477
+ "evidenceRefs",
2478
+ "gapRefs",
2479
+ "conflictRefs",
2480
+ ].includes(key)))
2481
+ return "decision_line_keys";
2482
+ const value_lineId = value["lineId"];
2483
+ if (typeof value_lineId !== "string" ||
2484
+ value_lineId.length < 1 ||
2485
+ value_lineId.length > 60)
2486
+ return "decision_line_id";
2487
+ const value_action = value["action"];
2488
+ if (typeof value_action !== "string" ||
2489
+ !["add", "retain", "replace", "remove", "review"].includes(value_action))
2490
+ return "decision_line_action";
2491
+ const value_code = value["code"];
2492
+ if (!isRecord(value_code))
2493
+ return "decision_line_code";
2494
+ if (!["code", "codeSystem"].every((key) => key in value_code))
2495
+ return "decision_line_code_keys";
2496
+ if (!Object.keys(value_code).every((key) => ["code", "codeSystem", "codeVersion"].includes(key)))
2497
+ return "decision_line_code_keys";
2498
+ const value_code_code = value_code["code"];
2499
+ if (typeof value_code_code !== "string" ||
2500
+ value_code_code.length < 1 ||
2501
+ value_code_code.length > 64 ||
2502
+ value_code_code.trim().length === 0)
2503
+ return "decision_line_code_value";
2504
+ const value_code_codeSystem = value_code["codeSystem"];
2505
+ if (typeof value_code_codeSystem !== "string" ||
2506
+ ![
2507
+ "ICD-10-CM",
2508
+ "ICD-10-PCS",
2509
+ "CPT",
2510
+ "HCPCS",
2511
+ "NDC",
2512
+ "CDT",
2513
+ "REVENUE_CODE",
2514
+ "DRG",
2515
+ "OTHER",
2516
+ ].includes(value_code_codeSystem))
2517
+ return "decision_line_code_system";
2518
+ if (value_code["codeVersion"] !== undefined) {
2519
+ const value_code_codeVersion = value_code["codeVersion"];
2520
+ if (typeof value_code_codeVersion !== "string" ||
2521
+ value_code_codeVersion.length < 1 ||
2522
+ value_code_codeVersion.length > 40)
2523
+ return "decision_line_code_version";
2524
+ }
2525
+ if (value["modifiers"] !== undefined) {
2526
+ const value_modifiers = value["modifiers"];
2527
+ if (!Array.isArray(value_modifiers) || value_modifiers.length > 8)
2528
+ return "decision_line_modifiers";
2529
+ for (const item of value_modifiers) {
2530
+ if (typeof item !== "string" || item.length < 1 || item.length > 8)
2531
+ return "decision_line_modifiers";
2532
+ }
2533
+ }
2534
+ if (value["units"] !== undefined) {
2535
+ const value_units = value["units"];
2536
+ if (!isRecord(value_units))
2537
+ return "decision_line_units";
2538
+ if (!Object.keys(value_units).every((key) => ["count", "unitOfMeasure"].includes(key)))
2539
+ return "decision_line_units_keys";
2540
+ if (value_units["count"] !== undefined) {
2541
+ const value_units_count = value_units["count"];
2542
+ if (typeof value_units_count !== "number" ||
2543
+ Number.isNaN(value_units_count) ||
2544
+ !Number.isInteger(value_units_count) ||
2545
+ value_units_count < 0 ||
2546
+ value_units_count > 999999)
2547
+ return "decision_line_units_count";
2548
+ }
2549
+ if (value_units["unitOfMeasure"] !== undefined) {
2550
+ const value_units_unitOfMeasure = value_units["unitOfMeasure"];
2551
+ if (typeof value_units_unitOfMeasure !== "string" ||
2552
+ value_units_unitOfMeasure.length < 1 ||
2553
+ value_units_unitOfMeasure.length > 20)
2554
+ return "decision_line_units_measure";
2555
+ }
2556
+ }
2557
+ if (value["linkedDiagnoses"] !== undefined) {
2558
+ const value_linkedDiagnoses = value["linkedDiagnoses"];
2559
+ if (!Array.isArray(value_linkedDiagnoses) ||
2560
+ value_linkedDiagnoses.length > 20)
2561
+ return "decision_line_linked_diagnoses";
2562
+ for (const item of value_linkedDiagnoses) {
2563
+ if (!isRecord(item))
2564
+ return "decision_line_linked_diagnosis";
2565
+ if (!["diagnosisRef"].every((key) => key in item))
2566
+ return "decision_line_linked_diagnosis_keys";
2567
+ if (!Object.keys(item).every((key) => ["diagnosisRef", "sequence"].includes(key)))
2568
+ return "decision_line_linked_diagnosis_keys";
2569
+ const item_diagnosisRef = item["diagnosisRef"];
2570
+ if (typeof item_diagnosisRef !== "string" ||
2571
+ item_diagnosisRef.length < 1 ||
2572
+ item_diagnosisRef.length > 60)
2573
+ return "decision_line_diagnosis_ref";
2574
+ if (item["sequence"] !== undefined) {
2575
+ const item_sequence = item["sequence"];
2576
+ if (typeof item_sequence !== "number" ||
2577
+ Number.isNaN(item_sequence) ||
2578
+ !Number.isInteger(item_sequence) ||
2579
+ item_sequence < 1 ||
2580
+ item_sequence > 99)
2581
+ return "decision_line_diagnosis_sequence";
2582
+ }
2583
+ }
2584
+ }
2585
+ if (value["sequence"] !== undefined) {
2586
+ const value_sequence = value["sequence"];
2587
+ if (typeof value_sequence !== "number" ||
2588
+ Number.isNaN(value_sequence) ||
2589
+ !Number.isInteger(value_sequence) ||
2590
+ value_sequence < 1 ||
2591
+ value_sequence > 999)
2592
+ return "decision_line_sequence";
2593
+ }
2594
+ const value_confidence = value["confidence"];
2595
+ if (typeof value_confidence !== "string" ||
2596
+ !["low", "medium", "high"].includes(value_confidence))
2597
+ return "decision_line_confidence";
2598
+ const value_rationale = value["rationale"];
2599
+ if (typeof value_rationale !== "string" ||
2600
+ value_rationale.length < 1 ||
2601
+ value_rationale.length > 2000 ||
2602
+ value_rationale.trim().length === 0)
2603
+ return "decision_line_rationale";
2604
+ if (value["evidenceRefs"] !== undefined) {
2605
+ const value_evidenceRefs = value["evidenceRefs"];
2606
+ if (!Array.isArray(value_evidenceRefs) || value_evidenceRefs.length > 10)
2607
+ return "decision_line_evidence_refs";
2608
+ for (const item of value_evidenceRefs) {
2609
+ if (typeof item !== "string" || item.length < 1 || item.length > 64)
2610
+ return "decision_line_evidence_refs";
2611
+ }
2612
+ }
2613
+ if (value["gapRefs"] !== undefined) {
2614
+ const value_gapRefs = value["gapRefs"];
2615
+ if (!Array.isArray(value_gapRefs) || value_gapRefs.length > 10)
2616
+ return "decision_line_gap_refs";
2617
+ for (const item of value_gapRefs) {
2618
+ if (typeof item !== "string" || item.length < 1 || item.length > 64)
2619
+ return "decision_line_gap_refs";
2620
+ }
2621
+ }
2622
+ if (value["conflictRefs"] !== undefined) {
2623
+ const value_conflictRefs = value["conflictRefs"];
2624
+ if (!Array.isArray(value_conflictRefs) || value_conflictRefs.length > 10)
2625
+ return "decision_line_conflict_refs";
2626
+ for (const item of value_conflictRefs) {
2627
+ if (typeof item !== "string" || item.length < 1 || item.length > 64)
2628
+ return "decision_line_conflict_refs";
2629
+ }
2630
+ }
2631
+ return null;
2632
+ }
2633
+ const validCodingDecisionLine = (value) => codingDecisionLineValidationError(value) === null;
2634
+ exports.validCodingDecisionLine = validCodingDecisionLine;
2635
+ exports.CodingDecisionLineSchemaJson = {
2636
+ $schema: "https://json-schema.org/draft/2020-12/schema",
2637
+ $id: "https://nexalink.care/contracts/coding-decision-line.schema.json",
2638
+ title: "CodingDecisionLine",
2639
+ description: "One proposed claim-line action within a CodingDecision. Actions are add, retain, replace, remove, or review; each line carries code identity, modifiers, units, linked diagnoses, sequencing, confidence, rationale, and evidence references.",
2640
+ version: "1.0.0",
2641
+ type: "object",
2642
+ additionalProperties: false,
2643
+ required: ["lineId", "action", "code", "confidence", "rationale"],
2644
+ properties: {
2645
+ lineId: {
2646
+ type: "string",
2647
+ minLength: 1,
2648
+ maxLength: 60,
2649
+ },
2650
+ action: {
2651
+ type: "string",
2652
+ enum: ["add", "retain", "replace", "remove", "review"],
2653
+ },
2654
+ code: {
2655
+ type: "object",
2656
+ additionalProperties: false,
2657
+ required: ["code", "codeSystem"],
2658
+ properties: {
2659
+ code: {
2660
+ type: "string",
2661
+ minLength: 1,
2662
+ maxLength: 64,
2663
+ },
2664
+ codeSystem: {
2665
+ type: "string",
2666
+ enum: [
2667
+ "ICD-10-CM",
2668
+ "ICD-10-PCS",
2669
+ "CPT",
2670
+ "HCPCS",
2671
+ "NDC",
2672
+ "CDT",
2673
+ "REVENUE_CODE",
2674
+ "DRG",
2675
+ "OTHER",
2676
+ ],
2677
+ },
2678
+ codeVersion: {
2679
+ type: "string",
2680
+ minLength: 1,
2681
+ maxLength: 40,
2682
+ },
2683
+ },
2684
+ },
2685
+ modifiers: {
2686
+ type: "array",
2687
+ maxItems: 8,
2688
+ items: {
2689
+ type: "string",
2690
+ minLength: 1,
2691
+ maxLength: 8,
2692
+ },
2693
+ },
2694
+ units: {
2695
+ type: "object",
2696
+ additionalProperties: false,
2697
+ properties: {
2698
+ count: {
2699
+ type: "integer",
2700
+ minimum: 0,
2701
+ maximum: 999999,
2702
+ },
2703
+ unitOfMeasure: {
2704
+ type: "string",
2705
+ minLength: 1,
2706
+ maxLength: 20,
2707
+ },
2708
+ },
2709
+ },
2710
+ linkedDiagnoses: {
2711
+ type: "array",
2712
+ maxItems: 20,
2713
+ items: {
2714
+ type: "object",
2715
+ additionalProperties: false,
2716
+ required: ["diagnosisRef"],
2717
+ properties: {
2718
+ diagnosisRef: {
2719
+ type: "string",
2720
+ minLength: 1,
2721
+ maxLength: 60,
2722
+ },
2723
+ sequence: {
2724
+ type: "integer",
2725
+ minimum: 1,
2726
+ maximum: 99,
2727
+ },
2728
+ },
2729
+ },
2730
+ },
2731
+ sequence: {
2732
+ type: "integer",
2733
+ minimum: 1,
2734
+ maximum: 999,
2735
+ },
2736
+ confidence: {
2737
+ type: "string",
2738
+ enum: ["low", "medium", "high"],
2739
+ },
2740
+ rationale: {
2741
+ type: "string",
2742
+ minLength: 1,
2743
+ maxLength: 2000,
2744
+ },
2745
+ evidenceRefs: {
2746
+ type: "array",
2747
+ maxItems: 10,
2748
+ items: {
2749
+ type: "string",
2750
+ minLength: 1,
2751
+ maxLength: 64,
2752
+ },
2753
+ },
2754
+ gapRefs: {
2755
+ type: "array",
2756
+ maxItems: 10,
2757
+ items: {
2758
+ type: "string",
2759
+ minLength: 1,
2760
+ maxLength: 64,
2761
+ },
2762
+ },
2763
+ conflictRefs: {
2764
+ type: "array",
2765
+ maxItems: 10,
2766
+ items: {
2767
+ type: "string",
2768
+ minLength: 1,
2769
+ maxLength: 64,
2770
+ },
2771
+ },
2772
+ },
2773
+ };
2774
+ // --------------------------------------------------------------------
2775
+ // CodingEvidence (schema 1.0.0, wire coding-evidence-v1)
2776
+ // --------------------------------------------------------------------
2777
+ exports.codingEvidenceSchema = zod_1.z
2778
+ .object({
2779
+ evidenceId: zod_1.z.string().min(1).max(64),
2780
+ type: zod_1.z.enum([
2781
+ "clinical",
2782
+ "coding_guideline",
2783
+ "payer_policy",
2784
+ "plan_policy",
2785
+ "contract_configuration",
2786
+ "terminology_validity",
2787
+ "rule_execution",
2788
+ ]),
2789
+ source: zod_1.z
2790
+ .string()
2791
+ .min(1)
2792
+ .max(240)
2793
+ .refine((value) => value.trim().length > 0),
2794
+ sourceVersion: zod_1.z.string().min(1).max(80),
2795
+ publisher: zod_1.z.string().min(1).max(240).optional(),
2796
+ scope: zod_1.z.enum(["national", "payer", "plan", "contract", "tenant"]),
2797
+ effectiveFrom: zod_1.z
2798
+ .string()
2799
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
2800
+ .refine(isIsoDate),
2801
+ effectiveTo: zod_1.z
2802
+ .string()
2803
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
2804
+ .refine(isIsoDate)
2805
+ .optional(),
2806
+ stableId: zod_1.z.string().min(1).max(240),
2807
+ excerpt: zod_1.z
2808
+ .string()
2809
+ .min(1)
2810
+ .max(2000)
2811
+ .refine((value) => value.trim().length > 0),
2812
+ retrievedAt: zod_1.z
2813
+ .string()
2814
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
2815
+ .refine(isIsoDate),
2816
+ })
2817
+ .strict();
2818
+ function codingEvidenceValidationError(value) {
2819
+ if (!isRecord(value))
2820
+ return "evidence";
2821
+ if (![
2822
+ "evidenceId",
2823
+ "type",
2824
+ "source",
2825
+ "sourceVersion",
2826
+ "scope",
2827
+ "effectiveFrom",
2828
+ "stableId",
2829
+ "excerpt",
2830
+ "retrievedAt",
2831
+ ].every((key) => key in value))
2832
+ return "evidence_keys";
2833
+ if (!Object.keys(value).every((key) => [
2834
+ "evidenceId",
2835
+ "type",
2836
+ "source",
2837
+ "sourceVersion",
2838
+ "publisher",
2839
+ "scope",
2840
+ "effectiveFrom",
2841
+ "effectiveTo",
2842
+ "stableId",
2843
+ "excerpt",
2844
+ "retrievedAt",
2845
+ ].includes(key)))
2846
+ return "evidence_keys";
2847
+ const value_evidenceId = value["evidenceId"];
2848
+ if (typeof value_evidenceId !== "string" ||
2849
+ value_evidenceId.length < 1 ||
2850
+ value_evidenceId.length > 64)
2851
+ return "evidence_id";
2852
+ const value_type = value["type"];
2853
+ if (typeof value_type !== "string" ||
2854
+ ![
2855
+ "clinical",
2856
+ "coding_guideline",
2857
+ "payer_policy",
2858
+ "plan_policy",
2859
+ "contract_configuration",
2860
+ "terminology_validity",
2861
+ "rule_execution",
2862
+ ].includes(value_type))
2863
+ return "evidence_type";
2864
+ const value_source = value["source"];
2865
+ if (typeof value_source !== "string" ||
2866
+ value_source.length < 1 ||
2867
+ value_source.length > 240 ||
2868
+ value_source.trim().length === 0)
2869
+ return "evidence_source";
2870
+ const value_sourceVersion = value["sourceVersion"];
2871
+ if (typeof value_sourceVersion !== "string" ||
2872
+ value_sourceVersion.length < 1 ||
2873
+ value_sourceVersion.length > 80)
2874
+ return "evidence_source_version";
2875
+ if (value["publisher"] !== undefined) {
2876
+ const value_publisher = value["publisher"];
2877
+ if (typeof value_publisher !== "string" ||
2878
+ value_publisher.length < 1 ||
2879
+ value_publisher.length > 240)
2880
+ return "evidence_publisher";
2881
+ }
2882
+ const value_scope = value["scope"];
2883
+ if (typeof value_scope !== "string" ||
2884
+ !["national", "payer", "plan", "contract", "tenant"].includes(value_scope))
2885
+ return "evidence_scope";
2886
+ const value_effectiveFrom = value["effectiveFrom"];
2887
+ if (typeof value_effectiveFrom !== "string" ||
2888
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(value_effectiveFrom) ||
2889
+ !isIsoDate(value_effectiveFrom))
2890
+ return "evidence_effective_from";
2891
+ if (value["effectiveTo"] !== undefined) {
2892
+ const value_effectiveTo = value["effectiveTo"];
2893
+ if (typeof value_effectiveTo !== "string" ||
2894
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(value_effectiveTo) ||
2895
+ !isIsoDate(value_effectiveTo))
2896
+ return "evidence_effective_to";
2897
+ }
2898
+ const value_stableId = value["stableId"];
2899
+ if (typeof value_stableId !== "string" ||
2900
+ value_stableId.length < 1 ||
2901
+ value_stableId.length > 240)
2902
+ return "evidence_stable_id";
2903
+ const value_excerpt = value["excerpt"];
2904
+ if (typeof value_excerpt !== "string" ||
2905
+ value_excerpt.length < 1 ||
2906
+ value_excerpt.length > 2000 ||
2907
+ value_excerpt.trim().length === 0)
2908
+ return "evidence_excerpt";
2909
+ const value_retrievedAt = value["retrievedAt"];
2910
+ if (typeof value_retrievedAt !== "string" ||
2911
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(value_retrievedAt) ||
2912
+ !isIsoDate(value_retrievedAt))
2913
+ return "evidence_retrieved_at";
2914
+ return null;
2915
+ }
2916
+ const validCodingEvidence = (value) => codingEvidenceValidationError(value) === null;
2917
+ exports.validCodingEvidence = validCodingEvidence;
2918
+ exports.CodingEvidenceSchemaJson = {
2919
+ $schema: "https://json-schema.org/draft/2020-12/schema",
2920
+ $id: "https://nexalink.care/contracts/coding-evidence.schema.json",
2921
+ title: "CodingEvidence",
2922
+ description: "One typed, traced evidence item attached to a decision. Every item carries source, scope, version, effective period, and a stable identifier so reviews can be reconstructed. Licensed terminology content is never distributed through evidence excerpts.",
2923
+ version: "1.0.0",
2924
+ type: "object",
2925
+ additionalProperties: false,
2926
+ required: [
2927
+ "evidenceId",
2928
+ "type",
2929
+ "source",
2930
+ "sourceVersion",
2931
+ "scope",
2932
+ "effectiveFrom",
2933
+ "stableId",
2934
+ "excerpt",
2935
+ "retrievedAt",
2936
+ ],
2937
+ properties: {
2938
+ evidenceId: {
2939
+ type: "string",
2940
+ minLength: 1,
2941
+ maxLength: 64,
2942
+ },
2943
+ type: {
2944
+ type: "string",
2945
+ enum: [
2946
+ "clinical",
2947
+ "coding_guideline",
2948
+ "payer_policy",
2949
+ "plan_policy",
2950
+ "contract_configuration",
2951
+ "terminology_validity",
2952
+ "rule_execution",
2953
+ ],
2954
+ },
2955
+ source: {
2956
+ type: "string",
2957
+ minLength: 1,
2958
+ maxLength: 240,
2959
+ },
2960
+ sourceVersion: {
2961
+ type: "string",
2962
+ minLength: 1,
2963
+ maxLength: 80,
2964
+ },
2965
+ publisher: {
2966
+ type: "string",
2967
+ minLength: 1,
2968
+ maxLength: 240,
2969
+ },
2970
+ scope: {
2971
+ type: "string",
2972
+ enum: ["national", "payer", "plan", "contract", "tenant"],
2973
+ },
2974
+ effectiveFrom: {
2975
+ type: "string",
2976
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
2977
+ format: "date",
2978
+ },
2979
+ effectiveTo: {
2980
+ type: "string",
2981
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
2982
+ format: "date",
2983
+ },
2984
+ stableId: {
2985
+ type: "string",
2986
+ minLength: 1,
2987
+ maxLength: 240,
2988
+ },
2989
+ excerpt: {
2990
+ type: "string",
2991
+ minLength: 1,
2992
+ maxLength: 2000,
2993
+ },
2994
+ retrievedAt: {
2995
+ type: "string",
2996
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
2997
+ format: "date",
2998
+ },
2999
+ },
3000
+ };
3001
+ // --------------------------------------------------------------------
3002
+ // CodingRuleResult (schema 1.0.0, wire coding-rule-result-v1)
3003
+ // --------------------------------------------------------------------
3004
+ exports.codingRuleResultSchema = zod_1.z
3005
+ .object({
3006
+ ruleId: zod_1.z.string().min(1).max(120),
3007
+ ruleVersion: zod_1.z.string().min(1).max(40),
3008
+ outcome: zod_1.z.enum([
3009
+ "satisfied",
3010
+ "failed",
3011
+ "rejected",
3012
+ "escalated",
3013
+ "conflicted",
3014
+ "warning",
3015
+ ]),
3016
+ severity: zod_1.z.enum(["info", "warning", "blocking"]).optional(),
3017
+ inputs: zod_1.z
3018
+ .array(zod_1.z
3019
+ .object({
3020
+ name: zod_1.z.string().min(1).max(80),
3021
+ value: zod_1.z.string().min(1).max(2000),
3022
+ })
3023
+ .strict())
3024
+ .max(30)
3025
+ .optional(),
3026
+ reason: zod_1.z.string().min(1).max(120).optional(),
3027
+ explanation: zod_1.z
3028
+ .string()
3029
+ .min(1)
3030
+ .max(1000)
3031
+ .refine((value) => value.trim().length > 0)
3032
+ .optional(),
3033
+ evidence: zod_1.z.string().min(1).max(2000).optional(),
3034
+ })
3035
+ .strict();
3036
+ function codingRuleResultValidationError(value) {
3037
+ if (!isRecord(value))
3038
+ return "rule_result";
3039
+ if (!["ruleId", "ruleVersion", "outcome"].every((key) => key in value))
3040
+ return "rule_result_keys";
3041
+ if (!Object.keys(value).every((key) => [
3042
+ "ruleId",
3043
+ "ruleVersion",
3044
+ "outcome",
3045
+ "severity",
3046
+ "inputs",
3047
+ "reason",
3048
+ "explanation",
3049
+ "evidence",
3050
+ ].includes(key)))
3051
+ return "rule_result_keys";
3052
+ const value_ruleId = value["ruleId"];
3053
+ if (typeof value_ruleId !== "string" ||
3054
+ value_ruleId.length < 1 ||
3055
+ value_ruleId.length > 120)
3056
+ return "rule_result_id";
3057
+ const value_ruleVersion = value["ruleVersion"];
3058
+ if (typeof value_ruleVersion !== "string" ||
3059
+ value_ruleVersion.length < 1 ||
3060
+ value_ruleVersion.length > 40)
3061
+ return "rule_result_version";
3062
+ const value_outcome = value["outcome"];
3063
+ if (typeof value_outcome !== "string" ||
3064
+ ![
3065
+ "satisfied",
3066
+ "failed",
3067
+ "rejected",
3068
+ "escalated",
3069
+ "conflicted",
3070
+ "warning",
3071
+ ].includes(value_outcome))
3072
+ return "rule_result_outcome";
3073
+ if (value["severity"] !== undefined) {
3074
+ const value_severity = value["severity"];
3075
+ if (typeof value_severity !== "string" ||
3076
+ !["info", "warning", "blocking"].includes(value_severity))
3077
+ return "rule_result_severity";
3078
+ }
3079
+ if (value["inputs"] !== undefined) {
3080
+ const value_inputs = value["inputs"];
3081
+ if (!Array.isArray(value_inputs) || value_inputs.length > 30)
3082
+ return "rule_result_inputs";
3083
+ for (const item of value_inputs) {
3084
+ if (!isRecord(item))
3085
+ return "rule_result_input";
3086
+ if (!["name", "value"].every((key) => key in item))
3087
+ return "rule_result_input_keys";
3088
+ if (!Object.keys(item).every((key) => ["name", "value"].includes(key)))
3089
+ return "rule_result_input_keys";
3090
+ const item_name = item["name"];
3091
+ if (typeof item_name !== "string" ||
3092
+ item_name.length < 1 ||
3093
+ item_name.length > 80)
3094
+ return "rule_result_input_name";
3095
+ const item_value = item["value"];
3096
+ if (typeof item_value !== "string" ||
3097
+ item_value.length < 1 ||
3098
+ item_value.length > 2000)
3099
+ return "rule_result_input_value";
3100
+ }
3101
+ }
3102
+ if (value["reason"] !== undefined) {
3103
+ const value_reason = value["reason"];
3104
+ if (typeof value_reason !== "string" ||
3105
+ value_reason.length < 1 ||
3106
+ value_reason.length > 120)
3107
+ return "rule_result_reason";
3108
+ }
3109
+ if (value["explanation"] !== undefined) {
3110
+ const value_explanation = value["explanation"];
3111
+ if (typeof value_explanation !== "string" ||
3112
+ value_explanation.length < 1 ||
3113
+ value_explanation.length > 1000 ||
3114
+ value_explanation.trim().length === 0)
3115
+ return "rule_result_explanation";
3116
+ }
3117
+ if (value["evidence"] !== undefined) {
3118
+ const value_evidence = value["evidence"];
3119
+ if (typeof value_evidence !== "string" ||
3120
+ value_evidence.length < 1 ||
3121
+ value_evidence.length > 2000)
3122
+ return "rule_result_evidence";
3123
+ }
3124
+ return null;
3125
+ }
3126
+ const validCodingRuleResult = (value) => codingRuleResultValidationError(value) === null;
3127
+ exports.validCodingRuleResult = validCodingRuleResult;
3128
+ exports.CodingRuleResultSchemaJson = {
3129
+ $schema: "https://json-schema.org/draft/2020-12/schema",
3130
+ $id: "https://nexalink.care/contracts/coding-rule-result.schema.json",
3131
+ title: "CodingRuleResult",
3132
+ description: "One deterministic rule execution trace attached to a decision. Rules never rely on the model for validity, bundling, sequencing, modifiers, units, or time calculations; each trace records the rule identity, version, inputs, outcome, and explanation needed to replay the decision.",
3133
+ version: "1.0.0",
3134
+ type: "object",
3135
+ additionalProperties: false,
3136
+ required: ["ruleId", "ruleVersion", "outcome"],
3137
+ properties: {
3138
+ ruleId: {
3139
+ type: "string",
3140
+ minLength: 1,
3141
+ maxLength: 120,
3142
+ },
3143
+ ruleVersion: {
3144
+ type: "string",
3145
+ minLength: 1,
3146
+ maxLength: 40,
3147
+ },
3148
+ outcome: {
3149
+ type: "string",
3150
+ enum: [
3151
+ "satisfied",
3152
+ "failed",
3153
+ "rejected",
3154
+ "escalated",
3155
+ "conflicted",
3156
+ "warning",
3157
+ ],
3158
+ },
3159
+ severity: {
3160
+ type: "string",
3161
+ enum: ["info", "warning", "blocking"],
3162
+ },
3163
+ inputs: {
3164
+ type: "array",
3165
+ maxItems: 30,
3166
+ items: {
3167
+ type: "object",
3168
+ additionalProperties: false,
3169
+ required: ["name", "value"],
3170
+ properties: {
3171
+ name: {
3172
+ type: "string",
3173
+ minLength: 1,
3174
+ maxLength: 80,
3175
+ },
3176
+ value: {
3177
+ type: "string",
3178
+ minLength: 1,
3179
+ maxLength: 2000,
3180
+ },
3181
+ },
3182
+ },
3183
+ },
3184
+ reason: {
3185
+ type: "string",
3186
+ minLength: 1,
3187
+ maxLength: 120,
3188
+ },
3189
+ explanation: {
3190
+ type: "string",
3191
+ minLength: 1,
3192
+ maxLength: 1000,
3193
+ },
3194
+ evidence: {
3195
+ type: "string",
3196
+ minLength: 1,
3197
+ maxLength: 2000,
3198
+ },
3199
+ },
3200
+ };
3201
+ // --------------------------------------------------------------------
3202
+ // CodingReviewerAction (schema 1.0.0, wire coding-reviewer-action-v1)
3203
+ // --------------------------------------------------------------------
3204
+ exports.codingReviewerActionSchema = zod_1.z
3205
+ .object({
3206
+ reviewerId: zod_1.z.string().min(1).max(128),
3207
+ reviewerRole: zod_1.z.string().min(1).max(80).optional(),
3208
+ action: zod_1.z.enum([
3209
+ "approved",
3210
+ "approved_with_changes",
3211
+ "rejected",
3212
+ "escalated",
3213
+ ]),
3214
+ resolutionCode: zod_1.z.string().min(1).max(80).optional(),
3215
+ notes: zod_1.z
3216
+ .string()
3217
+ .min(1)
3218
+ .max(2000)
3219
+ .refine((value) => value.trim().length > 0)
3220
+ .optional(),
3221
+ occurredAt: zod_1.z
3222
+ .string()
3223
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$"))
3224
+ .refine(isRfc3339DateTime)
3225
+ .max(64),
3226
+ })
3227
+ .strict();
3228
+ function codingReviewerActionValidationError(value) {
3229
+ if (!isRecord(value))
3230
+ return "reviewer_action";
3231
+ if (!["reviewerId", "action", "occurredAt"].every((key) => key in value))
3232
+ return "reviewer_action_keys";
3233
+ if (!Object.keys(value).every((key) => [
3234
+ "reviewerId",
3235
+ "reviewerRole",
3236
+ "action",
3237
+ "resolutionCode",
3238
+ "notes",
3239
+ "occurredAt",
3240
+ ].includes(key)))
3241
+ return "reviewer_action_keys";
3242
+ const value_reviewerId = value["reviewerId"];
3243
+ if (typeof value_reviewerId !== "string" ||
3244
+ value_reviewerId.length < 1 ||
3245
+ value_reviewerId.length > 128)
3246
+ return "reviewer_action_id";
3247
+ if (value["reviewerRole"] !== undefined) {
3248
+ const value_reviewerRole = value["reviewerRole"];
3249
+ if (typeof value_reviewerRole !== "string" ||
3250
+ value_reviewerRole.length < 1 ||
3251
+ value_reviewerRole.length > 80)
3252
+ return "reviewer_action_role";
3253
+ }
3254
+ const value_action = value["action"];
3255
+ if (typeof value_action !== "string" ||
3256
+ !["approved", "approved_with_changes", "rejected", "escalated"].includes(value_action))
3257
+ return "reviewer_action_type";
3258
+ if (value["resolutionCode"] !== undefined) {
3259
+ const value_resolutionCode = value["resolutionCode"];
3260
+ if (typeof value_resolutionCode !== "string" ||
3261
+ value_resolutionCode.length < 1 ||
3262
+ value_resolutionCode.length > 80)
3263
+ return "reviewer_action_resolution_code";
3264
+ }
3265
+ if (value["notes"] !== undefined) {
3266
+ const value_notes = value["notes"];
3267
+ if (typeof value_notes !== "string" ||
3268
+ value_notes.length < 1 ||
3269
+ value_notes.length > 2000 ||
3270
+ value_notes.trim().length === 0)
3271
+ return "reviewer_action_notes";
3272
+ }
3273
+ const value_occurredAt = value["occurredAt"];
3274
+ if (typeof value_occurredAt !== "string" ||
3275
+ value_occurredAt.length > 64 ||
3276
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$").test(value_occurredAt) ||
3277
+ !isRfc3339DateTime(value_occurredAt))
3278
+ return "reviewer_action_occurred_at";
3279
+ return null;
3280
+ }
3281
+ const validCodingReviewerAction = (value) => codingReviewerActionValidationError(value) === null;
3282
+ exports.validCodingReviewerAction = validCodingReviewerAction;
3283
+ exports.CodingReviewerActionSchemaJson = {
3284
+ $schema: "https://json-schema.org/draft/2020-12/schema",
3285
+ $id: "https://nexalink.care/contracts/coding-reviewer-action.schema.json",
3286
+ title: "CodingReviewerAction",
3287
+ description: "Attributable human-review disposition appended to an otherwise immutable decision. A decision plus its reviewer actions remains replayable: original and reviewer versions are both preserved.",
3288
+ version: "1.0.0",
3289
+ type: "object",
3290
+ additionalProperties: false,
3291
+ required: ["reviewerId", "action", "occurredAt"],
3292
+ properties: {
3293
+ reviewerId: {
3294
+ type: "string",
3295
+ minLength: 1,
3296
+ maxLength: 128,
3297
+ },
3298
+ reviewerRole: {
3299
+ type: "string",
3300
+ minLength: 1,
3301
+ maxLength: 80,
3302
+ },
3303
+ action: {
3304
+ type: "string",
3305
+ enum: ["approved", "approved_with_changes", "rejected", "escalated"],
3306
+ },
3307
+ resolutionCode: {
3308
+ type: "string",
3309
+ minLength: 1,
3310
+ maxLength: 80,
3311
+ },
3312
+ notes: {
3313
+ type: "string",
3314
+ minLength: 1,
3315
+ maxLength: 2000,
3316
+ },
3317
+ occurredAt: {
3318
+ type: "string",
3319
+ pattern: "^\\d{4}-\\d{2}-\\d{2}T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$",
3320
+ format: "date-time",
3321
+ maxLength: 64,
3322
+ },
3323
+ },
3324
+ };
3325
+ // --------------------------------------------------------------------
3326
+ // CodingDecision (schema 1.0.0, wire coding-decision-v1)
3327
+ // --------------------------------------------------------------------
3328
+ exports.codingDecisionSchema = zod_1.z
3329
+ .object({
3330
+ decisionId: zod_1.z.string().min(1).max(128),
3331
+ caseRef: zod_1.z.string().min(1).max(128),
3332
+ disposition: zod_1.z.enum(["review_required", "abstain", "escalate"]),
3333
+ humanReviewRequired: zod_1.z.literal(true),
3334
+ rationale: zod_1.z
3335
+ .string()
3336
+ .min(1)
3337
+ .max(4000)
3338
+ .refine((value) => value.trim().length > 0),
3339
+ overallConfidence: zod_1.z.enum(["low", "medium", "high"]).optional(),
3340
+ lineDecisions: zod_1.z.array(exports.codingDecisionLineSchema).max(100),
3341
+ facts: zod_1.z
3342
+ .array(zod_1.z
3343
+ .object({
3344
+ factId: zod_1.z.string().min(1).max(60),
3345
+ statement: zod_1.z
3346
+ .string()
3347
+ .min(1)
3348
+ .max(2000)
3349
+ .refine((value) => value.trim().length > 0),
3350
+ evidenceRefs: zod_1.z.array(zod_1.z.string().min(1).max(64)).max(10).optional(),
3351
+ })
3352
+ .strict())
3353
+ .max(50)
3354
+ .optional(),
3355
+ gaps: zod_1.z
3356
+ .array(zod_1.z
3357
+ .object({
3358
+ gapId: zod_1.z.string().min(1).max(60),
3359
+ type: zod_1.z.enum([
3360
+ "missing_documentation",
3361
+ "unsupported_scope",
3362
+ "insufficient_evidence",
3363
+ "policy_conflict",
3364
+ "terminology_unavailable",
3365
+ "other",
3366
+ ]),
3367
+ description: zod_1.z
3368
+ .string()
3369
+ .min(1)
3370
+ .max(1000)
3371
+ .refine((value) => value.trim().length > 0),
3372
+ severity: zod_1.z.enum(["low", "medium", "high", "blocking"]),
3373
+ })
3374
+ .strict())
3375
+ .max(30)
3376
+ .optional(),
3377
+ conflicts: zod_1.z
3378
+ .array(zod_1.z
3379
+ .object({
3380
+ conflictId: zod_1.z.string().min(1).max(60),
3381
+ type: zod_1.z.enum([
3382
+ "payer_vs_national",
3383
+ "plan_vs_contract",
3384
+ "terminology_period",
3385
+ "rule_vs_rule",
3386
+ "model_vs_rule",
3387
+ "other",
3388
+ ]),
3389
+ summary: zod_1.z
3390
+ .string()
3391
+ .min(1)
3392
+ .max(1000)
3393
+ .refine((value) => value.trim().length > 0),
3394
+ references: zod_1.z.array(zod_1.z.string().min(1).max(120)).max(10).optional(),
3395
+ })
3396
+ .strict())
3397
+ .max(20)
3398
+ .optional(),
3399
+ evidenceItems: zod_1.z.array(exports.codingEvidenceSchema).max(40).optional(),
3400
+ ruleTraces: zod_1.z.array(exports.codingRuleResultSchema).max(50).optional(),
3401
+ provenance: zod_1.z
3402
+ .object({
3403
+ decisionSchemaVersion: zod_1.z.string().min(1).max(40),
3404
+ caseSchemaVersion: zod_1.z.string().min(1).max(40),
3405
+ pack: zod_1.z
3406
+ .object({
3407
+ packId: zod_1.z.string().min(1).max(120),
3408
+ packVersion: zod_1.z.string().min(1).max(40),
3409
+ })
3410
+ .strict(),
3411
+ model: zod_1.z
3412
+ .object({
3413
+ modelId: zod_1.z.string().min(1).max(120),
3414
+ modelVersion: zod_1.z.string().min(1).max(40),
3415
+ })
3416
+ .strict(),
3417
+ terminology: zod_1.z
3418
+ .array(zod_1.z
3419
+ .object({
3420
+ system: zod_1.z.enum([
3421
+ "ICD-10-CM",
3422
+ "ICD-10-PCS",
3423
+ "CPT",
3424
+ "HCPCS",
3425
+ "NDC",
3426
+ "CDT",
3427
+ "REVENUE_CODE",
3428
+ "DRG",
3429
+ "MODIFIERS",
3430
+ "OTHER",
3431
+ ]),
3432
+ editionVersion: zod_1.z.string().min(1).max(40),
3433
+ licenseApproved: zod_1.z.boolean(),
3434
+ })
3435
+ .strict())
3436
+ .max(20),
3437
+ rules: zod_1.z
3438
+ .array(zod_1.z
3439
+ .object({
3440
+ ruleId: zod_1.z.string().min(1).max(120),
3441
+ ruleVersion: zod_1.z.string().min(1).max(40),
3442
+ })
3443
+ .strict())
3444
+ .max(30),
3445
+ retrievalCorpus: zod_1.z
3446
+ .object({
3447
+ corpusId: zod_1.z.string().min(1).max(120).optional(),
3448
+ corpusVersion: zod_1.z.string().min(1).max(120).optional(),
3449
+ })
3450
+ .strict()
3451
+ .optional(),
3452
+ generatedAt: zod_1.z
3453
+ .string()
3454
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$"))
3455
+ .refine(isRfc3339DateTime)
3456
+ .max(64),
3457
+ })
3458
+ .strict(),
3459
+ reviewerAction: exports.codingReviewerActionSchema.optional(),
3460
+ extensions: zod_1.z.array(exports.codingExtensionSchema).max(25).optional(),
3461
+ })
3462
+ .strict()
3463
+ .superRefine((value, ctx) => {
3464
+ if (value["disposition"] === "review_required") {
3465
+ if (!Array.isArray(value["lineDecisions"]) ||
3466
+ value["lineDecisions"].length === 0) {
3467
+ ctx.addIssue({
3468
+ code: "custom",
3469
+ path: ["lineDecisions"],
3470
+ message: "decision_review_required_lines",
3471
+ });
3472
+ }
3473
+ }
3474
+ else {
3475
+ if (Array.isArray(value["lineDecisions"]) &&
3476
+ value["lineDecisions"].length > 0) {
3477
+ ctx.addIssue({
3478
+ code: "custom",
3479
+ path: ["lineDecisions"],
3480
+ message: "decision_disposition_lines",
3481
+ });
3482
+ }
3483
+ }
3484
+ })
3485
+ .superRefine((value, ctx) => {
3486
+ const semanticValue = value;
3487
+ const provenance = isRecord(semanticValue["provenance"])
3488
+ ? semanticValue["provenance"]
3489
+ : {};
3490
+ if (Array.isArray(semanticValue["lineDecisions"]) &&
3491
+ semanticValue["lineDecisions"].length > 0 &&
3492
+ (!Array.isArray(provenance["terminology"]) ||
3493
+ provenance["terminology"].length === 0 ||
3494
+ !Array.isArray(provenance["rules"]) ||
3495
+ provenance["rules"].length === 0)) {
3496
+ ctx.addIssue({
3497
+ code: "custom",
3498
+ path: ["provenance"],
3499
+ message: "decision_provenance_replay",
3500
+ });
3501
+ }
3502
+ });
3503
+ function codingDecisionValidationError(value, options) {
3504
+ if (!isRecord(value))
3505
+ return "coding_decision";
3506
+ if (![
3507
+ "decisionId",
3508
+ "caseRef",
3509
+ "disposition",
3510
+ "humanReviewRequired",
3511
+ "rationale",
3512
+ "lineDecisions",
3513
+ "provenance",
3514
+ ].every((key) => key in value))
3515
+ return "coding_decision_keys";
3516
+ if (!Object.keys(value).every((key) => [
3517
+ "decisionId",
3518
+ "caseRef",
3519
+ "disposition",
3520
+ "humanReviewRequired",
3521
+ "rationale",
3522
+ "overallConfidence",
3523
+ "lineDecisions",
3524
+ "facts",
3525
+ "gaps",
3526
+ "conflicts",
3527
+ "evidenceItems",
3528
+ "ruleTraces",
3529
+ "provenance",
3530
+ "reviewerAction",
3531
+ "extensions",
3532
+ ].includes(key)))
3533
+ return "coding_decision_keys";
3534
+ const value_decisionId = value["decisionId"];
3535
+ if (typeof value_decisionId !== "string" ||
3536
+ value_decisionId.length < 1 ||
3537
+ value_decisionId.length > 128)
3538
+ return "decision_id";
3539
+ const value_caseRef = value["caseRef"];
3540
+ if (typeof value_caseRef !== "string" ||
3541
+ value_caseRef.length < 1 ||
3542
+ value_caseRef.length > 128)
3543
+ return "decision_case_ref";
3544
+ const value_disposition = value["disposition"];
3545
+ if (typeof value_disposition !== "string" ||
3546
+ !["review_required", "abstain", "escalate"].includes(value_disposition))
3547
+ return "decision_disposition";
3548
+ const value_humanReviewRequired = value["humanReviewRequired"];
3549
+ if (typeof value_humanReviewRequired !== "boolean" ||
3550
+ value_humanReviewRequired !== true)
3551
+ return "decision_human_review_required";
3552
+ const value_rationale = value["rationale"];
3553
+ if (typeof value_rationale !== "string" ||
3554
+ value_rationale.length < 1 ||
3555
+ value_rationale.length > 4000 ||
3556
+ value_rationale.trim().length === 0)
3557
+ return "decision_rationale";
3558
+ if (value["overallConfidence"] !== undefined) {
3559
+ const value_overallConfidence = value["overallConfidence"];
3560
+ if (typeof value_overallConfidence !== "string" ||
3561
+ !["low", "medium", "high"].includes(value_overallConfidence))
3562
+ return "decision_overall_confidence";
3563
+ }
3564
+ const value_lineDecisions = value["lineDecisions"];
3565
+ if (!Array.isArray(value_lineDecisions) || value_lineDecisions.length > 100)
3566
+ return "decision_lines";
3567
+ for (const item of value_lineDecisions) {
3568
+ const itemRefError = codingDecisionLineValidationError(item);
3569
+ if (itemRefError !== null)
3570
+ return itemRefError;
3571
+ }
3572
+ if (value["facts"] !== undefined) {
3573
+ const value_facts = value["facts"];
3574
+ if (!Array.isArray(value_facts) || value_facts.length > 50)
3575
+ return "decision_facts";
3576
+ for (const item of value_facts) {
3577
+ if (!isRecord(item))
3578
+ return "decision_fact";
3579
+ if (!["factId", "statement"].every((key) => key in item))
3580
+ return "decision_fact_keys";
3581
+ if (!Object.keys(item).every((key) => ["factId", "statement", "evidenceRefs"].includes(key)))
3582
+ return "decision_fact_keys";
3583
+ const item_factId = item["factId"];
3584
+ if (typeof item_factId !== "string" ||
3585
+ item_factId.length < 1 ||
3586
+ item_factId.length > 60)
3587
+ return "decision_fact_id";
3588
+ const item_statement = item["statement"];
3589
+ if (typeof item_statement !== "string" ||
3590
+ item_statement.length < 1 ||
3591
+ item_statement.length > 2000 ||
3592
+ item_statement.trim().length === 0)
3593
+ return "decision_fact_statement";
3594
+ if (item["evidenceRefs"] !== undefined) {
3595
+ const item_evidenceRefs = item["evidenceRefs"];
3596
+ if (!Array.isArray(item_evidenceRefs) || item_evidenceRefs.length > 10)
3597
+ return "decision_fact_evidence_refs";
3598
+ for (const item of item_evidenceRefs) {
3599
+ if (typeof item !== "string" || item.length < 1 || item.length > 64)
3600
+ return "decision_fact_evidence_refs";
3601
+ }
3602
+ }
3603
+ }
3604
+ }
3605
+ if (value["gaps"] !== undefined) {
3606
+ const value_gaps = value["gaps"];
3607
+ if (!Array.isArray(value_gaps) || value_gaps.length > 30)
3608
+ return "decision_gaps";
3609
+ for (const item of value_gaps) {
3610
+ if (!isRecord(item))
3611
+ return "decision_gap";
3612
+ if (!["gapId", "type", "description", "severity"].every((key) => key in item))
3613
+ return "decision_gap_keys";
3614
+ if (!Object.keys(item).every((key) => ["gapId", "type", "description", "severity"].includes(key)))
3615
+ return "decision_gap_keys";
3616
+ const item_gapId = item["gapId"];
3617
+ if (typeof item_gapId !== "string" ||
3618
+ item_gapId.length < 1 ||
3619
+ item_gapId.length > 60)
3620
+ return "decision_gap_id";
3621
+ const item_type = item["type"];
3622
+ if (typeof item_type !== "string" ||
3623
+ ![
3624
+ "missing_documentation",
3625
+ "unsupported_scope",
3626
+ "insufficient_evidence",
3627
+ "policy_conflict",
3628
+ "terminology_unavailable",
3629
+ "other",
3630
+ ].includes(item_type))
3631
+ return "decision_gap_type";
3632
+ const item_description = item["description"];
3633
+ if (typeof item_description !== "string" ||
3634
+ item_description.length < 1 ||
3635
+ item_description.length > 1000 ||
3636
+ item_description.trim().length === 0)
3637
+ return "decision_gap_description";
3638
+ const item_severity = item["severity"];
3639
+ if (typeof item_severity !== "string" ||
3640
+ !["low", "medium", "high", "blocking"].includes(item_severity))
3641
+ return "decision_gap_severity";
3642
+ }
3643
+ }
3644
+ if (value["conflicts"] !== undefined) {
3645
+ const value_conflicts = value["conflicts"];
3646
+ if (!Array.isArray(value_conflicts) || value_conflicts.length > 20)
3647
+ return "decision_conflicts";
3648
+ for (const item of value_conflicts) {
3649
+ if (!isRecord(item))
3650
+ return "decision_conflict";
3651
+ if (!["conflictId", "type", "summary"].every((key) => key in item))
3652
+ return "decision_conflict_keys";
3653
+ if (!Object.keys(item).every((key) => ["conflictId", "type", "summary", "references"].includes(key)))
3654
+ return "decision_conflict_keys";
3655
+ const item_conflictId = item["conflictId"];
3656
+ if (typeof item_conflictId !== "string" ||
3657
+ item_conflictId.length < 1 ||
3658
+ item_conflictId.length > 60)
3659
+ return "decision_conflict_id";
3660
+ const item_type = item["type"];
3661
+ if (typeof item_type !== "string" ||
3662
+ ![
3663
+ "payer_vs_national",
3664
+ "plan_vs_contract",
3665
+ "terminology_period",
3666
+ "rule_vs_rule",
3667
+ "model_vs_rule",
3668
+ "other",
3669
+ ].includes(item_type))
3670
+ return "decision_conflict_type";
3671
+ const item_summary = item["summary"];
3672
+ if (typeof item_summary !== "string" ||
3673
+ item_summary.length < 1 ||
3674
+ item_summary.length > 1000 ||
3675
+ item_summary.trim().length === 0)
3676
+ return "decision_conflict_summary";
3677
+ if (item["references"] !== undefined) {
3678
+ const item_references = item["references"];
3679
+ if (!Array.isArray(item_references) || item_references.length > 10)
3680
+ return "decision_conflict_references";
3681
+ for (const item of item_references) {
3682
+ if (typeof item !== "string" || item.length < 1 || item.length > 120)
3683
+ return "decision_conflict_references";
3684
+ }
3685
+ }
3686
+ }
3687
+ }
3688
+ if (value["evidenceItems"] !== undefined) {
3689
+ const value_evidenceItems = value["evidenceItems"];
3690
+ if (!Array.isArray(value_evidenceItems) || value_evidenceItems.length > 40)
3691
+ return "decision_evidence_items";
3692
+ for (const item of value_evidenceItems) {
3693
+ const itemRefError = codingEvidenceValidationError(item);
3694
+ if (itemRefError !== null)
3695
+ return itemRefError;
3696
+ }
3697
+ }
3698
+ if (value["ruleTraces"] !== undefined) {
3699
+ const value_ruleTraces = value["ruleTraces"];
3700
+ if (!Array.isArray(value_ruleTraces) || value_ruleTraces.length > 50)
3701
+ return "decision_rule_traces";
3702
+ for (const item of value_ruleTraces) {
3703
+ const itemRefError = codingRuleResultValidationError(item);
3704
+ if (itemRefError !== null)
3705
+ return itemRefError;
3706
+ }
3707
+ }
3708
+ const value_provenance = value["provenance"];
3709
+ if (!isRecord(value_provenance))
3710
+ return "decision_provenance";
3711
+ if (![
3712
+ "decisionSchemaVersion",
3713
+ "caseSchemaVersion",
3714
+ "pack",
3715
+ "model",
3716
+ "terminology",
3717
+ "rules",
3718
+ "generatedAt",
3719
+ ].every((key) => key in value_provenance))
3720
+ return "decision_provenance_keys";
3721
+ if (!Object.keys(value_provenance).every((key) => [
3722
+ "decisionSchemaVersion",
3723
+ "caseSchemaVersion",
3724
+ "pack",
3725
+ "model",
3726
+ "terminology",
3727
+ "rules",
3728
+ "retrievalCorpus",
3729
+ "generatedAt",
3730
+ ].includes(key)))
3731
+ return "decision_provenance_keys";
3732
+ const value_provenance_decisionSchemaVersion = value_provenance["decisionSchemaVersion"];
3733
+ if (typeof value_provenance_decisionSchemaVersion !== "string" ||
3734
+ value_provenance_decisionSchemaVersion.length < 1 ||
3735
+ value_provenance_decisionSchemaVersion.length > 40)
3736
+ return "decision_provenance_decision_schema_version";
3737
+ const value_provenance_caseSchemaVersion = value_provenance["caseSchemaVersion"];
3738
+ if (typeof value_provenance_caseSchemaVersion !== "string" ||
3739
+ value_provenance_caseSchemaVersion.length < 1 ||
3740
+ value_provenance_caseSchemaVersion.length > 40)
3741
+ return "decision_provenance_case_schema_version";
3742
+ const value_provenance_pack = value_provenance["pack"];
3743
+ if (!isRecord(value_provenance_pack))
3744
+ return "decision_provenance_pack";
3745
+ if (!["packId", "packVersion"].every((key) => key in value_provenance_pack))
3746
+ return "decision_provenance_pack_keys";
3747
+ if (!Object.keys(value_provenance_pack).every((key) => ["packId", "packVersion"].includes(key)))
3748
+ return "decision_provenance_pack_keys";
3749
+ const value_provenance_pack_packId = value_provenance_pack["packId"];
3750
+ if (typeof value_provenance_pack_packId !== "string" ||
3751
+ value_provenance_pack_packId.length < 1 ||
3752
+ value_provenance_pack_packId.length > 120)
3753
+ return "decision_provenance_pack_id";
3754
+ const value_provenance_pack_packVersion = value_provenance_pack["packVersion"];
3755
+ if (typeof value_provenance_pack_packVersion !== "string" ||
3756
+ value_provenance_pack_packVersion.length < 1 ||
3757
+ value_provenance_pack_packVersion.length > 40)
3758
+ return "decision_provenance_pack_version";
3759
+ const value_provenance_model = value_provenance["model"];
3760
+ if (!isRecord(value_provenance_model))
3761
+ return "decision_provenance_model";
3762
+ if (!["modelId", "modelVersion"].every((key) => key in value_provenance_model))
3763
+ return "decision_provenance_model_keys";
3764
+ if (!Object.keys(value_provenance_model).every((key) => ["modelId", "modelVersion"].includes(key)))
3765
+ return "decision_provenance_model_keys";
3766
+ const value_provenance_model_modelId = value_provenance_model["modelId"];
3767
+ if (typeof value_provenance_model_modelId !== "string" ||
3768
+ value_provenance_model_modelId.length < 1 ||
3769
+ value_provenance_model_modelId.length > 120)
3770
+ return "decision_provenance_model_id";
3771
+ const value_provenance_model_modelVersion = value_provenance_model["modelVersion"];
3772
+ if (typeof value_provenance_model_modelVersion !== "string" ||
3773
+ value_provenance_model_modelVersion.length < 1 ||
3774
+ value_provenance_model_modelVersion.length > 40)
3775
+ return "decision_provenance_model_version";
3776
+ const value_provenance_terminology = value_provenance["terminology"];
3777
+ if (!Array.isArray(value_provenance_terminology) ||
3778
+ value_provenance_terminology.length > 20)
3779
+ return "decision_provenance_terminology";
3780
+ for (const item of value_provenance_terminology) {
3781
+ if (!isRecord(item))
3782
+ return "decision_provenance_terminology_item";
3783
+ if (!["system", "editionVersion", "licenseApproved"].every((key) => key in item))
3784
+ return "decision_provenance_terminology_item_keys";
3785
+ if (!Object.keys(item).every((key) => ["system", "editionVersion", "licenseApproved"].includes(key)))
3786
+ return "decision_provenance_terminology_item_keys";
3787
+ const item_system = item["system"];
3788
+ if (typeof item_system !== "string" ||
3789
+ ![
3790
+ "ICD-10-CM",
3791
+ "ICD-10-PCS",
3792
+ "CPT",
3793
+ "HCPCS",
3794
+ "NDC",
3795
+ "CDT",
3796
+ "REVENUE_CODE",
3797
+ "DRG",
3798
+ "MODIFIERS",
3799
+ "OTHER",
3800
+ ].includes(item_system))
3801
+ return "decision_provenance_terminology_system";
3802
+ const item_editionVersion = item["editionVersion"];
3803
+ if (typeof item_editionVersion !== "string" ||
3804
+ item_editionVersion.length < 1 ||
3805
+ item_editionVersion.length > 40)
3806
+ return "decision_provenance_terminology_edition";
3807
+ const item_licenseApproved = item["licenseApproved"];
3808
+ if (typeof item_licenseApproved !== "boolean")
3809
+ return "decision_provenance_terminology_license";
3810
+ }
3811
+ const value_provenance_rules = value_provenance["rules"];
3812
+ if (!Array.isArray(value_provenance_rules) ||
3813
+ value_provenance_rules.length > 30)
3814
+ return "decision_provenance_rules";
3815
+ for (const item of value_provenance_rules) {
3816
+ if (!isRecord(item))
3817
+ return "decision_provenance_rule";
3818
+ if (!["ruleId", "ruleVersion"].every((key) => key in item))
3819
+ return "decision_provenance_rule_keys";
3820
+ if (!Object.keys(item).every((key) => ["ruleId", "ruleVersion"].includes(key)))
3821
+ return "decision_provenance_rule_keys";
3822
+ const item_ruleId = item["ruleId"];
3823
+ if (typeof item_ruleId !== "string" ||
3824
+ item_ruleId.length < 1 ||
3825
+ item_ruleId.length > 120)
3826
+ return "decision_provenance_rule_id";
3827
+ const item_ruleVersion = item["ruleVersion"];
3828
+ if (typeof item_ruleVersion !== "string" ||
3829
+ item_ruleVersion.length < 1 ||
3830
+ item_ruleVersion.length > 40)
3831
+ return "decision_provenance_rule_version";
3832
+ }
3833
+ if (value_provenance["retrievalCorpus"] !== undefined) {
3834
+ const value_provenance_retrievalCorpus = value_provenance["retrievalCorpus"];
3835
+ if (!isRecord(value_provenance_retrievalCorpus))
3836
+ return "decision_provenance_corpus";
3837
+ if (!Object.keys(value_provenance_retrievalCorpus).every((key) => ["corpusId", "corpusVersion"].includes(key)))
3838
+ return "decision_provenance_corpus_keys";
3839
+ if (value_provenance_retrievalCorpus["corpusId"] !== undefined) {
3840
+ const value_provenance_retrievalCorpus_corpusId = value_provenance_retrievalCorpus["corpusId"];
3841
+ if (typeof value_provenance_retrievalCorpus_corpusId !== "string" ||
3842
+ value_provenance_retrievalCorpus_corpusId.length < 1 ||
3843
+ value_provenance_retrievalCorpus_corpusId.length > 120)
3844
+ return "decision_provenance_corpus_id";
3845
+ }
3846
+ if (value_provenance_retrievalCorpus["corpusVersion"] !== undefined) {
3847
+ const value_provenance_retrievalCorpus_corpusVersion = value_provenance_retrievalCorpus["corpusVersion"];
3848
+ if (typeof value_provenance_retrievalCorpus_corpusVersion !== "string" ||
3849
+ value_provenance_retrievalCorpus_corpusVersion.length < 1 ||
3850
+ value_provenance_retrievalCorpus_corpusVersion.length > 120)
3851
+ return "decision_provenance_corpus_version";
3852
+ }
3853
+ }
3854
+ const value_provenance_generatedAt = value_provenance["generatedAt"];
3855
+ if (typeof value_provenance_generatedAt !== "string" ||
3856
+ value_provenance_generatedAt.length > 64 ||
3857
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$").test(value_provenance_generatedAt) ||
3858
+ !isRfc3339DateTime(value_provenance_generatedAt))
3859
+ return "decision_provenance_generated_at";
3860
+ if (value["reviewerAction"] !== undefined) {
3861
+ const value_reviewerAction = value["reviewerAction"];
3862
+ const value_reviewerActionRefError = codingReviewerActionValidationError(value_reviewerAction);
3863
+ if (value_reviewerActionRefError !== null)
3864
+ return value_reviewerActionRefError;
3865
+ }
3866
+ if (value["extensions"] !== undefined) {
3867
+ const value_extensions = value["extensions"];
3868
+ if (!Array.isArray(value_extensions) || value_extensions.length > 25)
3869
+ return "decision_extensions";
3870
+ for (const item of value_extensions) {
3871
+ const itemRefError = codingExtensionValidationError(item);
3872
+ if (itemRefError !== null)
3873
+ return itemRefError;
3874
+ }
3875
+ }
3876
+ if (value["disposition"] === "review_required") {
3877
+ if (!Array.isArray(value["lineDecisions"]) ||
3878
+ value["lineDecisions"].length === 0)
3879
+ return "decision_review_required_lines";
3880
+ }
3881
+ else {
3882
+ if (Array.isArray(value["lineDecisions"]) &&
3883
+ value["lineDecisions"].length > 0)
3884
+ return "decision_disposition_lines";
3885
+ }
3886
+ if (Array.isArray(value["lineDecisions"]) &&
3887
+ value["lineDecisions"].length > 0) {
3888
+ const provenance = isRecord(value["provenance"]) ? value["provenance"] : {};
3889
+ if (!Array.isArray(provenance["terminology"]) ||
3890
+ provenance["terminology"].length === 0 ||
3891
+ !Array.isArray(provenance["rules"]) ||
3892
+ provenance["rules"].length === 0)
3893
+ return "decision_provenance_replay";
3894
+ }
3895
+ return null;
3896
+ }
3897
+ const validCodingDecision = (value) => codingDecisionValidationError(value) === null;
3898
+ exports.validCodingDecision = validCodingDecision;
3899
+ exports.CodingDecisionSchemaJson = {
3900
+ $schema: "https://json-schema.org/draft/2020-12/schema",
3901
+ $id: "https://nexalink.care/contracts/coding-decision.schema.json",
3902
+ title: "CodingDecision",
3903
+ description: "The canonical, reconstructable decision for a CodingCase. caseRef is an analytics-safe reference (the case's analyticsId or a runtime opaque reference) and never a direct identifier. provenance pins the pack, model, terminology, rules, and schema versions needed to replay every recommendation.",
3904
+ version: "1.0.0",
3905
+ type: "object",
3906
+ additionalProperties: false,
3907
+ required: [
3908
+ "decisionId",
3909
+ "caseRef",
3910
+ "disposition",
3911
+ "humanReviewRequired",
3912
+ "rationale",
3913
+ "lineDecisions",
3914
+ "provenance",
3915
+ ],
3916
+ properties: {
3917
+ decisionId: {
3918
+ type: "string",
3919
+ minLength: 1,
3920
+ maxLength: 128,
3921
+ },
3922
+ caseRef: {
3923
+ type: "string",
3924
+ minLength: 1,
3925
+ maxLength: 128,
3926
+ },
3927
+ disposition: {
3928
+ type: "string",
3929
+ enum: ["review_required", "abstain", "escalate"],
3930
+ },
3931
+ humanReviewRequired: {
3932
+ type: "boolean",
3933
+ const: true,
3934
+ },
3935
+ rationale: {
3936
+ type: "string",
3937
+ minLength: 1,
3938
+ maxLength: 4000,
3939
+ },
3940
+ overallConfidence: {
3941
+ type: "string",
3942
+ enum: ["low", "medium", "high"],
3943
+ },
3944
+ lineDecisions: {
3945
+ type: "array",
3946
+ maxItems: 100,
3947
+ items: {
3948
+ $ref: "coding-decision-line.schema.json",
3949
+ },
3950
+ },
3951
+ facts: {
3952
+ type: "array",
3953
+ maxItems: 50,
3954
+ items: {
3955
+ type: "object",
3956
+ additionalProperties: false,
3957
+ required: ["factId", "statement"],
3958
+ properties: {
3959
+ factId: {
3960
+ type: "string",
3961
+ minLength: 1,
3962
+ maxLength: 60,
3963
+ },
3964
+ statement: {
3965
+ type: "string",
3966
+ minLength: 1,
3967
+ maxLength: 2000,
3968
+ },
3969
+ evidenceRefs: {
3970
+ type: "array",
3971
+ maxItems: 10,
3972
+ items: {
3973
+ type: "string",
3974
+ minLength: 1,
3975
+ maxLength: 64,
3976
+ },
3977
+ },
3978
+ },
3979
+ },
3980
+ },
3981
+ gaps: {
3982
+ type: "array",
3983
+ maxItems: 30,
3984
+ items: {
3985
+ type: "object",
3986
+ additionalProperties: false,
3987
+ required: ["gapId", "type", "description", "severity"],
3988
+ properties: {
3989
+ gapId: {
3990
+ type: "string",
3991
+ minLength: 1,
3992
+ maxLength: 60,
3993
+ },
3994
+ type: {
3995
+ type: "string",
3996
+ enum: [
3997
+ "missing_documentation",
3998
+ "unsupported_scope",
3999
+ "insufficient_evidence",
4000
+ "policy_conflict",
4001
+ "terminology_unavailable",
4002
+ "other",
4003
+ ],
4004
+ },
4005
+ description: {
4006
+ type: "string",
4007
+ minLength: 1,
4008
+ maxLength: 1000,
4009
+ },
4010
+ severity: {
4011
+ type: "string",
4012
+ enum: ["low", "medium", "high", "blocking"],
4013
+ },
4014
+ },
4015
+ },
4016
+ },
4017
+ conflicts: {
4018
+ type: "array",
4019
+ maxItems: 20,
4020
+ items: {
4021
+ type: "object",
4022
+ additionalProperties: false,
4023
+ required: ["conflictId", "type", "summary"],
4024
+ properties: {
4025
+ conflictId: {
4026
+ type: "string",
4027
+ minLength: 1,
4028
+ maxLength: 60,
4029
+ },
4030
+ type: {
4031
+ type: "string",
4032
+ enum: [
4033
+ "payer_vs_national",
4034
+ "plan_vs_contract",
4035
+ "terminology_period",
4036
+ "rule_vs_rule",
4037
+ "model_vs_rule",
4038
+ "other",
4039
+ ],
4040
+ },
4041
+ summary: {
4042
+ type: "string",
4043
+ minLength: 1,
4044
+ maxLength: 1000,
4045
+ },
4046
+ references: {
4047
+ type: "array",
4048
+ maxItems: 10,
4049
+ items: {
4050
+ type: "string",
4051
+ minLength: 1,
4052
+ maxLength: 120,
4053
+ },
4054
+ },
4055
+ },
4056
+ },
4057
+ },
4058
+ evidenceItems: {
4059
+ type: "array",
4060
+ maxItems: 40,
4061
+ items: {
4062
+ $ref: "coding-evidence.schema.json",
4063
+ },
4064
+ },
4065
+ ruleTraces: {
4066
+ type: "array",
4067
+ maxItems: 50,
4068
+ items: {
4069
+ $ref: "coding-rule-result.schema.json",
4070
+ },
4071
+ },
4072
+ provenance: {
4073
+ type: "object",
4074
+ additionalProperties: false,
4075
+ required: [
4076
+ "decisionSchemaVersion",
4077
+ "caseSchemaVersion",
4078
+ "pack",
4079
+ "model",
4080
+ "terminology",
4081
+ "rules",
4082
+ "generatedAt",
4083
+ ],
4084
+ properties: {
4085
+ decisionSchemaVersion: {
4086
+ type: "string",
4087
+ minLength: 1,
4088
+ maxLength: 40,
4089
+ },
4090
+ caseSchemaVersion: {
4091
+ type: "string",
4092
+ minLength: 1,
4093
+ maxLength: 40,
4094
+ },
4095
+ pack: {
4096
+ type: "object",
4097
+ additionalProperties: false,
4098
+ required: ["packId", "packVersion"],
4099
+ properties: {
4100
+ packId: {
4101
+ type: "string",
4102
+ minLength: 1,
4103
+ maxLength: 120,
4104
+ },
4105
+ packVersion: {
4106
+ type: "string",
4107
+ minLength: 1,
4108
+ maxLength: 40,
4109
+ },
4110
+ },
4111
+ },
4112
+ model: {
4113
+ type: "object",
4114
+ additionalProperties: false,
4115
+ required: ["modelId", "modelVersion"],
4116
+ properties: {
4117
+ modelId: {
4118
+ type: "string",
4119
+ minLength: 1,
4120
+ maxLength: 120,
4121
+ },
4122
+ modelVersion: {
4123
+ type: "string",
4124
+ minLength: 1,
4125
+ maxLength: 40,
4126
+ },
4127
+ },
4128
+ },
4129
+ terminology: {
4130
+ type: "array",
4131
+ maxItems: 20,
4132
+ items: {
4133
+ type: "object",
4134
+ additionalProperties: false,
4135
+ required: ["system", "editionVersion", "licenseApproved"],
4136
+ properties: {
4137
+ system: {
4138
+ type: "string",
4139
+ enum: [
4140
+ "ICD-10-CM",
4141
+ "ICD-10-PCS",
4142
+ "CPT",
4143
+ "HCPCS",
4144
+ "NDC",
4145
+ "CDT",
4146
+ "REVENUE_CODE",
4147
+ "DRG",
4148
+ "MODIFIERS",
4149
+ "OTHER",
4150
+ ],
4151
+ },
4152
+ editionVersion: {
4153
+ type: "string",
4154
+ minLength: 1,
4155
+ maxLength: 40,
4156
+ },
4157
+ licenseApproved: {
4158
+ type: "boolean",
4159
+ },
4160
+ },
4161
+ },
4162
+ },
4163
+ rules: {
4164
+ type: "array",
4165
+ maxItems: 30,
4166
+ items: {
4167
+ type: "object",
4168
+ additionalProperties: false,
4169
+ required: ["ruleId", "ruleVersion"],
4170
+ properties: {
4171
+ ruleId: {
4172
+ type: "string",
4173
+ minLength: 1,
4174
+ maxLength: 120,
4175
+ },
4176
+ ruleVersion: {
4177
+ type: "string",
4178
+ minLength: 1,
4179
+ maxLength: 40,
4180
+ },
4181
+ },
4182
+ },
4183
+ },
4184
+ retrievalCorpus: {
4185
+ type: "object",
4186
+ additionalProperties: false,
4187
+ properties: {
4188
+ corpusId: {
4189
+ type: "string",
4190
+ minLength: 1,
4191
+ maxLength: 120,
4192
+ },
4193
+ corpusVersion: {
4194
+ type: "string",
4195
+ minLength: 1,
4196
+ maxLength: 120,
4197
+ },
4198
+ },
4199
+ },
4200
+ generatedAt: {
4201
+ type: "string",
4202
+ pattern: "^\\d{4}-\\d{2}-\\d{2}T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$",
4203
+ format: "date-time",
4204
+ maxLength: 64,
4205
+ },
4206
+ },
4207
+ },
4208
+ reviewerAction: {
4209
+ $ref: "coding-reviewer-action.schema.json",
4210
+ },
4211
+ extensions: {
4212
+ type: "array",
4213
+ maxItems: 25,
4214
+ items: {
4215
+ $ref: "coding-extension.schema.json",
4216
+ },
4217
+ },
4218
+ },
4219
+ if: {
4220
+ properties: {
4221
+ disposition: {
4222
+ const: "review_required",
4223
+ },
4224
+ },
4225
+ required: ["disposition"],
4226
+ },
4227
+ then: {
4228
+ properties: {
4229
+ lineDecisions: {
4230
+ minItems: 1,
4231
+ },
4232
+ provenance: {
4233
+ properties: {
4234
+ terminology: {
4235
+ minItems: 1,
4236
+ },
4237
+ rules: {
4238
+ minItems: 1,
4239
+ },
4240
+ },
4241
+ },
4242
+ },
4243
+ },
4244
+ else: {
4245
+ properties: {
4246
+ lineDecisions: {
4247
+ maxItems: 0,
4248
+ },
4249
+ },
4250
+ },
4251
+ };
4252
+ // --------------------------------------------------------------------
31
4253
  // RcmSupportingReference (schema 1.0.0, wire rcm-supporting-reference-v1)
32
4254
  // --------------------------------------------------------------------
33
4255
  exports.rcmSupportingReferenceSchema = zod_1.z
@@ -58,6 +4280,8 @@ exports.rcmSupportingReferenceSchema = zod_1.z
58
4280
  function rcmSupportingReferenceValidationError(value) {
59
4281
  if (!isRecord(value))
60
4282
  return "reference";
4283
+ if (!["referenceId", "title", "excerpt"].every((key) => key in value))
4284
+ return "reference_keys";
61
4285
  if (!Object.keys(value).every((key) => [
62
4286
  "referenceId",
63
4287
  "documentId",
@@ -71,8 +4295,7 @@ function rcmSupportingReferenceValidationError(value) {
71
4295
  "coveredPayerProgram",
72
4296
  "sourceUrl",
73
4297
  "humanReviewRequired",
74
- ].includes(key)) ||
75
- !["referenceId", "title", "excerpt"].every((key) => key in value))
4298
+ ].includes(key)))
76
4299
  return "reference_keys";
77
4300
  const value_referenceId = value["referenceId"];
78
4301
  if (typeof value_referenceId !== "string" ||
@@ -242,6 +4465,8 @@ exports.rcmCodingInputSchema = zod_1.z
242
4465
  function rcmCodingInputValidationError(value) {
243
4466
  if (!isRecord(value))
244
4467
  return "coding_input";
4468
+ if (!["encounterId", "diagnosisNarrative"].every((key) => key in value))
4469
+ return "coding_input_keys";
245
4470
  if (!Object.keys(value).every((key) => [
246
4471
  "encounterId",
247
4472
  "diagnosisNarrative",
@@ -250,8 +4475,7 @@ function rcmCodingInputValidationError(value) {
250
4475
  "placeOfService",
251
4476
  "claimContext",
252
4477
  "supportingReferences",
253
- ].includes(key)) ||
254
- !["encounterId", "diagnosisNarrative"].every((key) => key in value))
4478
+ ].includes(key)))
255
4479
  return "coding_input_keys";
256
4480
  const value_encounterId = value["encounterId"];
257
4481
  if (typeof value_encounterId !== "string" ||
@@ -318,9 +4542,9 @@ function rcmCodingInputValidationError(value) {
318
4542
  value_supportingReferences.length > 10)
319
4543
  return "supporting_references";
320
4544
  for (const item of value_supportingReferences) {
321
- const itemError = rcmSupportingReferenceValidationError(item);
322
- if (itemError !== null)
323
- return itemError;
4545
+ const itemRefError = rcmSupportingReferenceValidationError(item);
4546
+ if (itemRefError !== null)
4547
+ return itemRefError;
324
4548
  }
325
4549
  }
326
4550
  return null;
@@ -465,20 +4689,21 @@ exports.rcmCodingOutputSchema = zod_1.z
465
4689
  function rcmCodingOutputValidationError(value, options) {
466
4690
  if (!isRecord(value))
467
4691
  return "not_object";
4692
+ if (![
4693
+ "disposition",
4694
+ "humanReviewRequired",
4695
+ "recommendations",
4696
+ "documentationGaps",
4697
+ "rationale",
4698
+ ].every((key) => key in value))
4699
+ return "top_level_keys";
468
4700
  if (!Object.keys(value).every((key) => [
469
4701
  "disposition",
470
4702
  "humanReviewRequired",
471
4703
  "rationale",
472
4704
  "recommendations",
473
4705
  "documentationGaps",
474
- ].includes(key)) ||
475
- ![
476
- "disposition",
477
- "humanReviewRequired",
478
- "recommendations",
479
- "documentationGaps",
480
- "rationale",
481
- ].every((key) => key in value))
4706
+ ].includes(key)))
482
4707
  return "top_level_keys";
483
4708
  const value_disposition = value["disposition"];
484
4709
  if (typeof value_disposition !== "string" ||
@@ -501,14 +4726,15 @@ function rcmCodingOutputValidationError(value, options) {
501
4726
  for (const item of value_recommendations) {
502
4727
  if (!isRecord(item))
503
4728
  return "recommendation_keys";
4729
+ if (!["code", "codeSystem", "confidence", "rationale", "evidenceIds"].every((key) => key in item))
4730
+ return "recommendation_keys";
504
4731
  if (!Object.keys(item).every((key) => [
505
4732
  "code",
506
4733
  "codeSystem",
507
4734
  "confidence",
508
4735
  "rationale",
509
4736
  "evidenceIds",
510
- ].includes(key)) ||
511
- !["code", "codeSystem", "confidence", "rationale", "evidenceIds"].every((key) => key in item))
4737
+ ].includes(key)))
512
4738
  return "recommendation_keys";
513
4739
  const item_code = item["code"];
514
4740
  if (typeof item_code !== "string" ||
@@ -737,12 +4963,15 @@ exports.rcmModelPromptSchema = zod_1.z
737
4963
  function rcmModelPromptValidationError(value) {
738
4964
  if (!isRecord(value))
739
4965
  return "model_prompt";
740
- if (!Object.keys(value).every((key) => ["encounter", "supportingReferences"].includes(key)) ||
741
- !["encounter", "supportingReferences"].every((key) => key in value))
4966
+ if (!["encounter", "supportingReferences"].every((key) => key in value))
4967
+ return "model_prompt_keys";
4968
+ if (!Object.keys(value).every((key) => ["encounter", "supportingReferences"].includes(key)))
742
4969
  return "model_prompt_keys";
743
4970
  const value_encounter = value["encounter"];
744
4971
  if (!isRecord(value_encounter))
745
4972
  return "encounter";
4973
+ if (!["encounterId", "diagnosisNarrative"].every((key) => key in value_encounter))
4974
+ return "encounter_keys";
746
4975
  if (!Object.keys(value_encounter).every((key) => [
747
4976
  "encounterId",
748
4977
  "diagnosisNarrative",
@@ -750,8 +4979,7 @@ function rcmModelPromptValidationError(value) {
750
4979
  "serviceDate",
751
4980
  "placeOfService",
752
4981
  "claimContext",
753
- ].includes(key)) ||
754
- !["encounterId", "diagnosisNarrative"].every((key) => key in value_encounter))
4982
+ ].includes(key)))
755
4983
  return "encounter_keys";
756
4984
  const value_encounter_encounterId = value_encounter["encounterId"];
757
4985
  if (typeof value_encounter_encounterId !== "string" ||
@@ -817,9 +5045,9 @@ function rcmModelPromptValidationError(value) {
817
5045
  value_supportingReferences.length > 5)
818
5046
  return "model_prompt_references";
819
5047
  for (const item of value_supportingReferences) {
820
- const itemError = rcmSupportingReferenceValidationError(item);
821
- if (itemError !== null)
822
- return itemError;
5048
+ const itemRefError = rcmSupportingReferenceValidationError(item);
5049
+ if (itemRefError !== null)
5050
+ return itemRefError;
823
5051
  }
824
5052
  return null;
825
5053
  }
@@ -915,6 +5143,8 @@ exports.rcmRetrievalMetadataSchema = zod_1.z
915
5143
  function rcmRetrievalMetadataValidationError(value) {
916
5144
  if (!isRecord(value))
917
5145
  return "retrieval_metadata";
5146
+ if (!["corpusId", "corpusVersion", "outcome", "latencyMs", "references"].every((key) => key in value))
5147
+ return "retrieval_metadata_keys";
918
5148
  if (!Object.keys(value).every((key) => [
919
5149
  "corpusId",
920
5150
  "corpusVersion",
@@ -923,8 +5153,7 @@ function rcmRetrievalMetadataValidationError(value) {
923
5153
  "knowledgeBaseId",
924
5154
  "tenantId",
925
5155
  "references",
926
- ].includes(key)) ||
927
- !["corpusId", "corpusVersion", "outcome", "latencyMs", "references"].every((key) => key in value))
5156
+ ].includes(key)))
928
5157
  return "retrieval_metadata_keys";
929
5158
  const value_corpusId = value["corpusId"];
930
5159
  if (typeof value_corpusId !== "string" ||
@@ -961,9 +5190,9 @@ function rcmRetrievalMetadataValidationError(value) {
961
5190
  if (!Array.isArray(value_references))
962
5191
  return "retrieval_references";
963
5192
  for (const item of value_references) {
964
- const itemError = rcmSupportingReferenceValidationError(item);
965
- if (itemError !== null)
966
- return itemError;
5193
+ const itemRefError = rcmSupportingReferenceValidationError(item);
5194
+ if (itemRefError !== null)
5195
+ return itemRefError;
967
5196
  }
968
5197
  return null;
969
5198
  }
@@ -1075,6 +5304,8 @@ exports.rcmRuntimeEventSchema = zod_1.z
1075
5304
  function rcmRuntimeEventValidationError(value) {
1076
5305
  if (!isRecord(value))
1077
5306
  return "runtime_event";
5307
+ if (!["type", "outcome", "reason", "occurredAt", "workflowId"].every((key) => key in value))
5308
+ return "runtime_event_keys";
1078
5309
  if (!Object.keys(value).every((key) => [
1079
5310
  "type",
1080
5311
  "outcome",
@@ -1083,8 +5314,7 @@ function rcmRuntimeEventValidationError(value) {
1083
5314
  "workflowId",
1084
5315
  "guardrail",
1085
5316
  "retrieval",
1086
- ].includes(key)) ||
1087
- !["type", "outcome", "reason", "occurredAt", "workflowId"].every((key) => key in value))
5317
+ ].includes(key)))
1088
5318
  return "runtime_event_keys";
1089
5319
  const value_type = value["type"];
1090
5320
  if (typeof value_type !== "string" ||
@@ -1134,8 +5364,9 @@ function rcmRuntimeEventValidationError(value) {
1134
5364
  for (const item of value_guardrail_actions) {
1135
5365
  if (!isRecord(item))
1136
5366
  return "runtime_event_guardrail_action";
1137
- if (!Object.keys(item).every((key) => ["scope", "policyType", "rule", "action"].includes(key)) ||
1138
- !["scope", "policyType", "rule", "action"].every((key) => key in item))
5367
+ if (!["scope", "policyType", "rule", "action"].every((key) => key in item))
5368
+ return "runtime_event_guardrail_action_keys";
5369
+ if (!Object.keys(item).every((key) => ["scope", "policyType", "rule", "action"].includes(key)))
1139
5370
  return "runtime_event_guardrail_action_keys";
1140
5371
  const item_scope = item["scope"];
1141
5372
  if (typeof item_scope !== "string" || item_scope.length > 64)
@@ -1156,6 +5387,15 @@ function rcmRuntimeEventValidationError(value) {
1156
5387
  const value_retrieval = value["retrieval"];
1157
5388
  if (!isRecord(value_retrieval))
1158
5389
  return "runtime_event_retrieval";
5390
+ if (![
5391
+ "corpusId",
5392
+ "corpusVersion",
5393
+ "outcome",
5394
+ "referenceCount",
5395
+ "latencyMs",
5396
+ "references",
5397
+ ].every((key) => key in value_retrieval))
5398
+ return "runtime_event_retrieval_keys";
1159
5399
  if (!Object.keys(value_retrieval).every((key) => [
1160
5400
  "corpusId",
1161
5401
  "corpusVersion",
@@ -1163,15 +5403,7 @@ function rcmRuntimeEventValidationError(value) {
1163
5403
  "referenceCount",
1164
5404
  "latencyMs",
1165
5405
  "references",
1166
- ].includes(key)) ||
1167
- ![
1168
- "corpusId",
1169
- "corpusVersion",
1170
- "outcome",
1171
- "referenceCount",
1172
- "latencyMs",
1173
- "references",
1174
- ].every((key) => key in value_retrieval))
5406
+ ].includes(key)))
1175
5407
  return "runtime_event_retrieval_keys";
1176
5408
  const value_retrieval_corpusId = value_retrieval["corpusId"];
1177
5409
  if (typeof value_retrieval_corpusId !== "string" ||
@@ -1205,8 +5437,9 @@ function rcmRuntimeEventValidationError(value) {
1205
5437
  for (const item of value_retrieval_references) {
1206
5438
  if (!isRecord(item))
1207
5439
  return "runtime_event_retrieval_reference";
1208
- if (!Object.keys(item).every((key) => ["referenceId", "documentId", "version"].includes(key)) ||
1209
- !["referenceId", "documentId", "version"].every((key) => key in item))
5440
+ if (!["referenceId", "documentId", "version"].every((key) => key in item))
5441
+ return "runtime_event_retrieval_reference_keys";
5442
+ if (!Object.keys(item).every((key) => ["referenceId", "documentId", "version"].includes(key)))
1210
5443
  return "runtime_event_retrieval_reference_keys";
1211
5444
  const item_referenceId = item["referenceId"];
1212
5445
  if (typeof item_referenceId !== "string" ||
@@ -1398,6 +5631,16 @@ exports.rcmWorkflowCatalogSchema = zod_1.z
1398
5631
  function rcmWorkflowCatalogValidationError(value) {
1399
5632
  if (!isRecord(value))
1400
5633
  return "workflow_catalog";
5634
+ if (![
5635
+ "id",
5636
+ "name",
5637
+ "description",
5638
+ "environments",
5639
+ "modelPolicy",
5640
+ "humanReviewPolicy",
5641
+ "outputSchemaVersion",
5642
+ ].every((key) => key in value))
5643
+ return "workflow_catalog_keys";
1401
5644
  if (!Object.keys(value).every((key) => [
1402
5645
  "id",
1403
5646
  "name",
@@ -1406,16 +5649,7 @@ function rcmWorkflowCatalogValidationError(value) {
1406
5649
  "modelPolicy",
1407
5650
  "humanReviewPolicy",
1408
5651
  "outputSchemaVersion",
1409
- ].includes(key)) ||
1410
- ![
1411
- "id",
1412
- "name",
1413
- "description",
1414
- "environments",
1415
- "modelPolicy",
1416
- "humanReviewPolicy",
1417
- "outputSchemaVersion",
1418
- ].every((key) => key in value))
5652
+ ].includes(key)))
1419
5653
  return "workflow_catalog_keys";
1420
5654
  const value_id = value["id"];
1421
5655
  if (typeof value_id !== "string" ||
@@ -1442,6 +5676,15 @@ function rcmWorkflowCatalogValidationError(value) {
1442
5676
  const value_modelPolicy = value["modelPolicy"];
1443
5677
  if (!isRecord(value_modelPolicy))
1444
5678
  return "model_policy";
5679
+ if (![
5680
+ "policyId",
5681
+ "inferencePath",
5682
+ "maxNewTokens",
5683
+ "temperature",
5684
+ "outputSchemaVersion",
5685
+ "requireHumanReview",
5686
+ ].every((key) => key in value_modelPolicy))
5687
+ return "model_policy_keys";
1445
5688
  if (!Object.keys(value_modelPolicy).every((key) => [
1446
5689
  "policyId",
1447
5690
  "inferencePath",
@@ -1449,15 +5692,7 @@ function rcmWorkflowCatalogValidationError(value) {
1449
5692
  "temperature",
1450
5693
  "outputSchemaVersion",
1451
5694
  "requireHumanReview",
1452
- ].includes(key)) ||
1453
- ![
1454
- "policyId",
1455
- "inferencePath",
1456
- "maxNewTokens",
1457
- "temperature",
1458
- "outputSchemaVersion",
1459
- "requireHumanReview",
1460
- ].every((key) => key in value_modelPolicy))
5695
+ ].includes(key)))
1461
5696
  return "model_policy_keys";
1462
5697
  const value_modelPolicy_policyId = value_modelPolicy["policyId"];
1463
5698
  if (typeof value_modelPolicy_policyId !== "string" ||
@@ -1491,8 +5726,9 @@ function rcmWorkflowCatalogValidationError(value) {
1491
5726
  const value_humanReviewPolicy = value["humanReviewPolicy"];
1492
5727
  if (!isRecord(value_humanReviewPolicy))
1493
5728
  return "human_review_policy";
1494
- if (!Object.keys(value_humanReviewPolicy).every((key) => ["policyId", "humanReviewRequired"].includes(key)) ||
1495
- !["policyId", "humanReviewRequired"].every((key) => key in value_humanReviewPolicy))
5729
+ if (!["policyId", "humanReviewRequired"].every((key) => key in value_humanReviewPolicy))
5730
+ return "human_review_policy_keys";
5731
+ if (!Object.keys(value_humanReviewPolicy).every((key) => ["policyId", "humanReviewRequired"].includes(key)))
1496
5732
  return "human_review_policy_keys";
1497
5733
  const value_humanReviewPolicy_policyId = value_humanReviewPolicy["policyId"];
1498
5734
  if (typeof value_humanReviewPolicy_policyId !== "string" ||