@nexalink/coding-contracts 0.1.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.
@@ -0,0 +1,1613 @@
1
+ "use strict";
2
+ // GENERATED FILE. DO NOT EDIT.
3
+ // Source: nexalink-cloud contracts/ (run: npm run contracts:gen)
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;
6
+ exports.rcmSupportingReferenceValidationError = rcmSupportingReferenceValidationError;
7
+ exports.rcmCodingInputValidationError = rcmCodingInputValidationError;
8
+ exports.rcmCodingOutputValidationError = rcmCodingOutputValidationError;
9
+ exports.rcmModelPromptValidationError = rcmModelPromptValidationError;
10
+ exports.rcmRetrievalMetadataValidationError = rcmRetrievalMetadataValidationError;
11
+ exports.rcmRuntimeEventValidationError = rcmRuntimeEventValidationError;
12
+ exports.rcmWorkflowCatalogValidationError = rcmWorkflowCatalogValidationError;
13
+ const zod_1 = require("zod");
14
+ const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
15
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
16
+ // Canonical workflow constants (source: contracts/workflow-constants.json).
17
+ exports.RCM_WORKFLOW_ID = "rcm-coding-assistance";
18
+ exports.RCM_MODEL_POLICY_ID = "carecompass-rcm-review-v1";
19
+ exports.RCM_HUMAN_REVIEW_POLICY_ID = "qualified-coder-review-v1";
20
+ exports.RCM_OUTPUT_SCHEMA_NAME = "carecompass_rcm_grounded_review";
21
+ exports.RCM_HUMAN_REVIEW_INSTRUCTION = "Qualified human coder review is required before billing, coding, or claim submission.";
22
+ // Schema wire versions (source: contracts/schemas/*.schema.json).
23
+ exports.RCM_REFERENCE_SCHEMA_VERSION = "rcm-supporting-reference-v1";
24
+ exports.RCM_INPUT_SCHEMA_VERSION = "rcm-coding-input-v1";
25
+ exports.RCM_OUTPUT_SCHEMA_VERSION = "rcm-grounded-human-review-v2";
26
+ exports.RCM_MODEL_PROMPT_SCHEMA_VERSION = "rcm-model-prompt-v1";
27
+ exports.RCM_RETRIEVAL_SCHEMA_VERSION = "rcm-retrieval-metadata-v1";
28
+ exports.RCM_RUNTIME_EVENT_SCHEMA_VERSION = "rcm-runtime-event-v1";
29
+ exports.RCM_WORKFLOW_CATALOG_SCHEMA_VERSION = "rcm-workflow-catalog-v1";
30
+ // --------------------------------------------------------------------
31
+ // RcmSupportingReference (schema 1.0.0, wire rcm-supporting-reference-v1)
32
+ // --------------------------------------------------------------------
33
+ exports.rcmSupportingReferenceSchema = zod_1.z
34
+ .object({
35
+ referenceId: zod_1.z
36
+ .string()
37
+ .regex(new RegExp("^reference-[1-9][0-9]*$"))
38
+ .max(32),
39
+ documentId: zod_1.z.string().min(1).max(240).optional(),
40
+ title: zod_1.z.string().min(1).max(240),
41
+ excerpt: zod_1.z.string().min(1).max(2000),
42
+ version: zod_1.z.string().min(1).max(80).optional(),
43
+ corpusScope: zod_1.z.enum(["base", "tenant"]).optional(),
44
+ publisher: zod_1.z.string().max(240).optional(),
45
+ effectiveDate: zod_1.z
46
+ .string()
47
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
48
+ .optional(),
49
+ retrievalDate: zod_1.z
50
+ .string()
51
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
52
+ .optional(),
53
+ coveredPayerProgram: zod_1.z.string().max(240).optional(),
54
+ sourceUrl: zod_1.z.string().max(2048).optional(),
55
+ humanReviewRequired: zod_1.z.literal(true).optional(),
56
+ })
57
+ .strict();
58
+ function rcmSupportingReferenceValidationError(value) {
59
+ if (!isRecord(value))
60
+ return "reference";
61
+ if (!Object.keys(value).every((key) => [
62
+ "referenceId",
63
+ "documentId",
64
+ "title",
65
+ "excerpt",
66
+ "version",
67
+ "corpusScope",
68
+ "publisher",
69
+ "effectiveDate",
70
+ "retrievalDate",
71
+ "coveredPayerProgram",
72
+ "sourceUrl",
73
+ "humanReviewRequired",
74
+ ].includes(key)) ||
75
+ !["referenceId", "title", "excerpt"].every((key) => key in value))
76
+ return "reference_keys";
77
+ const value_referenceId = value["referenceId"];
78
+ if (typeof value_referenceId !== "string" ||
79
+ value_referenceId.length > 32 ||
80
+ !new RegExp("^reference-[1-9][0-9]*$").test(value_referenceId))
81
+ return "reference_id";
82
+ if (value["documentId"] !== undefined) {
83
+ const value_documentId = value["documentId"];
84
+ if (typeof value_documentId !== "string" ||
85
+ value_documentId.length < 1 ||
86
+ value_documentId.length > 240)
87
+ return "reference_document_id";
88
+ }
89
+ const value_title = value["title"];
90
+ if (typeof value_title !== "string" ||
91
+ value_title.length < 1 ||
92
+ value_title.length > 240)
93
+ return "reference_title";
94
+ const value_excerpt = value["excerpt"];
95
+ if (typeof value_excerpt !== "string" ||
96
+ value_excerpt.length < 1 ||
97
+ value_excerpt.length > 2000)
98
+ return "reference_excerpt";
99
+ if (value["version"] !== undefined) {
100
+ const value_version = value["version"];
101
+ if (typeof value_version !== "string" ||
102
+ value_version.length < 1 ||
103
+ value_version.length > 80)
104
+ return "reference_version";
105
+ }
106
+ if (value["corpusScope"] !== undefined) {
107
+ const value_corpusScope = value["corpusScope"];
108
+ if (typeof value_corpusScope !== "string" ||
109
+ !["base", "tenant"].includes(value_corpusScope))
110
+ return "reference_corpus_scope";
111
+ }
112
+ if (value["publisher"] !== undefined) {
113
+ const value_publisher = value["publisher"];
114
+ if (typeof value_publisher !== "string" || value_publisher.length > 240)
115
+ return "reference_publisher";
116
+ }
117
+ if (value["effectiveDate"] !== undefined) {
118
+ const value_effectiveDate = value["effectiveDate"];
119
+ if (typeof value_effectiveDate !== "string" ||
120
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(value_effectiveDate))
121
+ return "reference_effective_date";
122
+ }
123
+ if (value["retrievalDate"] !== undefined) {
124
+ const value_retrievalDate = value["retrievalDate"];
125
+ if (typeof value_retrievalDate !== "string" ||
126
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(value_retrievalDate))
127
+ return "reference_retrieval_date";
128
+ }
129
+ if (value["coveredPayerProgram"] !== undefined) {
130
+ const value_coveredPayerProgram = value["coveredPayerProgram"];
131
+ if (typeof value_coveredPayerProgram !== "string" ||
132
+ value_coveredPayerProgram.length > 240)
133
+ return "reference_covered_payer_program";
134
+ }
135
+ if (value["sourceUrl"] !== undefined) {
136
+ const value_sourceUrl = value["sourceUrl"];
137
+ if (typeof value_sourceUrl !== "string" || value_sourceUrl.length > 2048)
138
+ return "reference_source_url";
139
+ }
140
+ if (value["humanReviewRequired"] !== undefined) {
141
+ const value_humanReviewRequired = value["humanReviewRequired"];
142
+ if (typeof value_humanReviewRequired !== "boolean" ||
143
+ value_humanReviewRequired !== true)
144
+ return "reference_human_review_required";
145
+ }
146
+ return null;
147
+ }
148
+ const validRcmSupportingReference = (value) => rcmSupportingReferenceValidationError(value) === null;
149
+ exports.validRcmSupportingReference = validRcmSupportingReference;
150
+ exports.RcmSupportingReferenceSchemaJson = {
151
+ $schema: "https://json-schema.org/draft/2020-12/schema",
152
+ $id: "https://nexalink.care/contracts/rcm-supporting-reference.schema.json",
153
+ title: "RcmSupportingReference",
154
+ description: "One policy/evidence reference attached to an RCM coding request or returned by the tenant-scoped hosted retrieval. Core fields are the portable minimum; the remaining fields are populated by the hosted runtime and may be absent for customer-injected development references.",
155
+ version: "1.0.0",
156
+ type: "object",
157
+ additionalProperties: false,
158
+ required: ["referenceId", "title", "excerpt"],
159
+ properties: {
160
+ referenceId: {
161
+ type: "string",
162
+ pattern: "^reference-[1-9][0-9]*$",
163
+ maxLength: 32,
164
+ },
165
+ documentId: {
166
+ type: "string",
167
+ minLength: 1,
168
+ maxLength: 240,
169
+ },
170
+ title: {
171
+ type: "string",
172
+ minLength: 1,
173
+ maxLength: 240,
174
+ },
175
+ excerpt: {
176
+ type: "string",
177
+ minLength: 1,
178
+ maxLength: 2000,
179
+ },
180
+ version: {
181
+ type: "string",
182
+ minLength: 1,
183
+ maxLength: 80,
184
+ },
185
+ corpusScope: {
186
+ type: "string",
187
+ enum: ["base", "tenant"],
188
+ },
189
+ publisher: {
190
+ type: "string",
191
+ maxLength: 240,
192
+ },
193
+ effectiveDate: {
194
+ type: "string",
195
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
196
+ },
197
+ retrievalDate: {
198
+ type: "string",
199
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
200
+ },
201
+ coveredPayerProgram: {
202
+ type: "string",
203
+ maxLength: 240,
204
+ },
205
+ sourceUrl: {
206
+ type: "string",
207
+ maxLength: 2048,
208
+ },
209
+ humanReviewRequired: {
210
+ type: "boolean",
211
+ const: true,
212
+ },
213
+ },
214
+ };
215
+ // --------------------------------------------------------------------
216
+ // RcmCodingInput (schema 1.0.0, wire rcm-coding-input-v1)
217
+ // --------------------------------------------------------------------
218
+ exports.rcmCodingInputSchema = zod_1.z
219
+ .object({
220
+ encounterId: zod_1.z.string().min(1).max(160),
221
+ diagnosisNarrative: zod_1.z.string().min(1).max(2000),
222
+ procedureNarrative: zod_1.z.string().max(2000).optional(),
223
+ serviceDate: zod_1.z
224
+ .string()
225
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
226
+ .optional(),
227
+ placeOfService: zod_1.z.string().min(1).max(20).optional(),
228
+ claimContext: zod_1.z
229
+ .object({
230
+ stage: zod_1.z.enum(["development", "staging", "production"]).optional(),
231
+ payerName: zod_1.z.string().min(1).max(160).optional(),
232
+ submittedCodes: zod_1.z.array(zod_1.z.string().min(1).max(20)).max(20).optional(),
233
+ })
234
+ .strict()
235
+ .optional(),
236
+ supportingReferences: zod_1.z
237
+ .array(exports.rcmSupportingReferenceSchema)
238
+ .max(10)
239
+ .optional(),
240
+ })
241
+ .strict();
242
+ function rcmCodingInputValidationError(value) {
243
+ if (!isRecord(value))
244
+ return "coding_input";
245
+ if (!Object.keys(value).every((key) => [
246
+ "encounterId",
247
+ "diagnosisNarrative",
248
+ "procedureNarrative",
249
+ "serviceDate",
250
+ "placeOfService",
251
+ "claimContext",
252
+ "supportingReferences",
253
+ ].includes(key)) ||
254
+ !["encounterId", "diagnosisNarrative"].every((key) => key in value))
255
+ return "coding_input_keys";
256
+ const value_encounterId = value["encounterId"];
257
+ if (typeof value_encounterId !== "string" ||
258
+ value_encounterId.length < 1 ||
259
+ value_encounterId.length > 160)
260
+ return "encounter_id";
261
+ const value_diagnosisNarrative = value["diagnosisNarrative"];
262
+ if (typeof value_diagnosisNarrative !== "string" ||
263
+ value_diagnosisNarrative.length < 1 ||
264
+ value_diagnosisNarrative.length > 2000)
265
+ return "diagnosis_narrative";
266
+ if (value["procedureNarrative"] !== undefined) {
267
+ const value_procedureNarrative = value["procedureNarrative"];
268
+ if (typeof value_procedureNarrative !== "string" ||
269
+ value_procedureNarrative.length > 2000)
270
+ return "procedure_narrative";
271
+ }
272
+ if (value["serviceDate"] !== undefined) {
273
+ const value_serviceDate = value["serviceDate"];
274
+ if (typeof value_serviceDate !== "string" ||
275
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(value_serviceDate))
276
+ return "service_date";
277
+ }
278
+ if (value["placeOfService"] !== undefined) {
279
+ const value_placeOfService = value["placeOfService"];
280
+ if (typeof value_placeOfService !== "string" ||
281
+ value_placeOfService.length < 1 ||
282
+ value_placeOfService.length > 20)
283
+ return "place_of_service";
284
+ }
285
+ if (value["claimContext"] !== undefined) {
286
+ const value_claimContext = value["claimContext"];
287
+ if (!isRecord(value_claimContext))
288
+ return "claim_context";
289
+ if (!Object.keys(value_claimContext).every((key) => ["stage", "payerName", "submittedCodes"].includes(key)))
290
+ return "claim_context";
291
+ if (value_claimContext["stage"] !== undefined) {
292
+ const value_claimContext_stage = value_claimContext["stage"];
293
+ if (typeof value_claimContext_stage !== "string" ||
294
+ !["development", "staging", "production"].includes(value_claimContext_stage))
295
+ return "claim_context_stage";
296
+ }
297
+ if (value_claimContext["payerName"] !== undefined) {
298
+ const value_claimContext_payerName = value_claimContext["payerName"];
299
+ if (typeof value_claimContext_payerName !== "string" ||
300
+ value_claimContext_payerName.length < 1 ||
301
+ value_claimContext_payerName.length > 160)
302
+ return "claim_context_payer_name";
303
+ }
304
+ if (value_claimContext["submittedCodes"] !== undefined) {
305
+ const value_claimContext_submittedCodes = value_claimContext["submittedCodes"];
306
+ if (!Array.isArray(value_claimContext_submittedCodes) ||
307
+ value_claimContext_submittedCodes.length > 20)
308
+ return "claim_context_submitted_codes";
309
+ for (const item of value_claimContext_submittedCodes) {
310
+ if (typeof item !== "string" || item.length < 1 || item.length > 20)
311
+ return "claim_context_submitted_codes";
312
+ }
313
+ }
314
+ }
315
+ if (value["supportingReferences"] !== undefined) {
316
+ const value_supportingReferences = value["supportingReferences"];
317
+ if (!Array.isArray(value_supportingReferences) ||
318
+ value_supportingReferences.length > 10)
319
+ return "supporting_references";
320
+ for (const item of value_supportingReferences) {
321
+ const itemError = rcmSupportingReferenceValidationError(item);
322
+ if (itemError !== null)
323
+ return itemError;
324
+ }
325
+ }
326
+ return null;
327
+ }
328
+ const validRcmCodingInput = (value) => rcmCodingInputValidationError(value) === null;
329
+ exports.validRcmCodingInput = validRcmCodingInput;
330
+ exports.RcmCodingInputSchemaJson = {
331
+ $schema: "https://json-schema.org/draft/2020-12/schema",
332
+ $id: "https://nexalink.care/contracts/rcm-coding-input.schema.json",
333
+ title: "RcmCodingInput",
334
+ description: "Structured coding-case context for a single encounter-based RCM coding-review request. Canonical source for the SDK input shape, the portal request context, and the cloud-hosted encounter payload.",
335
+ version: "1.0.0",
336
+ type: "object",
337
+ additionalProperties: false,
338
+ required: ["encounterId", "diagnosisNarrative"],
339
+ properties: {
340
+ encounterId: {
341
+ type: "string",
342
+ minLength: 1,
343
+ maxLength: 160,
344
+ },
345
+ diagnosisNarrative: {
346
+ type: "string",
347
+ minLength: 1,
348
+ maxLength: 2000,
349
+ },
350
+ procedureNarrative: {
351
+ type: "string",
352
+ maxLength: 2000,
353
+ },
354
+ serviceDate: {
355
+ type: "string",
356
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
357
+ },
358
+ placeOfService: {
359
+ type: "string",
360
+ minLength: 1,
361
+ maxLength: 20,
362
+ },
363
+ claimContext: {
364
+ type: "object",
365
+ additionalProperties: false,
366
+ properties: {
367
+ stage: {
368
+ type: "string",
369
+ enum: ["development", "staging", "production"],
370
+ },
371
+ payerName: {
372
+ type: "string",
373
+ minLength: 1,
374
+ maxLength: 160,
375
+ },
376
+ submittedCodes: {
377
+ type: "array",
378
+ maxItems: 20,
379
+ items: {
380
+ type: "string",
381
+ minLength: 1,
382
+ maxLength: 20,
383
+ },
384
+ },
385
+ },
386
+ },
387
+ supportingReferences: {
388
+ type: "array",
389
+ maxItems: 10,
390
+ items: {
391
+ $ref: "rcm-supporting-reference.schema.json",
392
+ },
393
+ },
394
+ },
395
+ };
396
+ // --------------------------------------------------------------------
397
+ // RcmCodingOutput (schema 1.0.0, wire rcm-grounded-human-review-v2)
398
+ // --------------------------------------------------------------------
399
+ exports.rcmCodingOutputSchema = zod_1.z
400
+ .object({
401
+ disposition: zod_1.z.enum(["review_required", "abstain", "escalate"]),
402
+ humanReviewRequired: zod_1.z.literal(true),
403
+ rationale: zod_1.z
404
+ .string()
405
+ .min(1)
406
+ .max(4000)
407
+ .refine((value) => value.trim().length > 0),
408
+ recommendations: zod_1.z
409
+ .array(zod_1.z
410
+ .object({
411
+ code: zod_1.z
412
+ .string()
413
+ .min(1)
414
+ .max(64)
415
+ .refine((value) => value.trim().length > 0),
416
+ codeSystem: zod_1.z.enum(["ICD-10-CM", "CPT", "HCPCS"]),
417
+ confidence: zod_1.z.enum(["low", "medium", "high"]),
418
+ rationale: zod_1.z
419
+ .string()
420
+ .min(1)
421
+ .max(2000)
422
+ .refine((value) => value.trim().length > 0),
423
+ evidenceIds: zod_1.z
424
+ .array(zod_1.z
425
+ .string()
426
+ .min(1)
427
+ .max(128)
428
+ .refine((value) => value.trim().length > 0))
429
+ .min(1)
430
+ .max(5),
431
+ })
432
+ .strict())
433
+ .max(20),
434
+ documentationGaps: zod_1.z
435
+ .array(zod_1.z
436
+ .string()
437
+ .min(1)
438
+ .max(1000)
439
+ .refine((value) => value.trim().length > 0))
440
+ .max(20),
441
+ })
442
+ .strict()
443
+ .superRefine((value, ctx) => {
444
+ if (value["disposition"] === "review_required") {
445
+ if (!Array.isArray(value["recommendations"]) ||
446
+ value["recommendations"].length === 0) {
447
+ ctx.addIssue({
448
+ code: "custom",
449
+ path: ["recommendations"],
450
+ message: "review_required_recommendations",
451
+ });
452
+ }
453
+ }
454
+ else {
455
+ if (Array.isArray(value["recommendations"]) &&
456
+ value["recommendations"].length > 0) {
457
+ ctx.addIssue({
458
+ code: "custom",
459
+ path: ["recommendations"],
460
+ message: "disposition_recommendations",
461
+ });
462
+ }
463
+ }
464
+ });
465
+ function rcmCodingOutputValidationError(value, options) {
466
+ if (!isRecord(value))
467
+ return "not_object";
468
+ if (!Object.keys(value).every((key) => [
469
+ "disposition",
470
+ "humanReviewRequired",
471
+ "rationale",
472
+ "recommendations",
473
+ "documentationGaps",
474
+ ].includes(key)) ||
475
+ ![
476
+ "disposition",
477
+ "humanReviewRequired",
478
+ "recommendations",
479
+ "documentationGaps",
480
+ "rationale",
481
+ ].every((key) => key in value))
482
+ return "top_level_keys";
483
+ const value_disposition = value["disposition"];
484
+ if (typeof value_disposition !== "string" ||
485
+ !["review_required", "abstain", "escalate"].includes(value_disposition))
486
+ return "disposition";
487
+ const value_humanReviewRequired = value["humanReviewRequired"];
488
+ if (typeof value_humanReviewRequired !== "boolean" ||
489
+ value_humanReviewRequired !== true)
490
+ return "human_review_required";
491
+ const value_rationale = value["rationale"];
492
+ if (typeof value_rationale !== "string" ||
493
+ value_rationale.length < 1 ||
494
+ value_rationale.length > 4000 ||
495
+ value_rationale.trim().length === 0)
496
+ return "rationale";
497
+ const value_recommendations = value["recommendations"];
498
+ if (!Array.isArray(value_recommendations) ||
499
+ value_recommendations.length > 20)
500
+ return "recommendations";
501
+ for (const item of value_recommendations) {
502
+ if (!isRecord(item))
503
+ return "recommendation_keys";
504
+ if (!Object.keys(item).every((key) => [
505
+ "code",
506
+ "codeSystem",
507
+ "confidence",
508
+ "rationale",
509
+ "evidenceIds",
510
+ ].includes(key)) ||
511
+ !["code", "codeSystem", "confidence", "rationale", "evidenceIds"].every((key) => key in item))
512
+ return "recommendation_keys";
513
+ const item_code = item["code"];
514
+ if (typeof item_code !== "string" ||
515
+ item_code.length < 1 ||
516
+ item_code.length > 64 ||
517
+ item_code.trim().length === 0)
518
+ return "recommendation_code";
519
+ const item_codeSystem = item["codeSystem"];
520
+ if (typeof item_codeSystem !== "string" ||
521
+ !["ICD-10-CM", "CPT", "HCPCS"].includes(item_codeSystem))
522
+ return "recommendation_code_system";
523
+ const item_confidence = item["confidence"];
524
+ if (typeof item_confidence !== "string" ||
525
+ !["low", "medium", "high"].includes(item_confidence))
526
+ return "recommendation_confidence";
527
+ const item_rationale = item["rationale"];
528
+ if (typeof item_rationale !== "string" ||
529
+ item_rationale.length < 1 ||
530
+ item_rationale.length > 2000 ||
531
+ item_rationale.trim().length === 0)
532
+ return "recommendation_rationale";
533
+ const item_evidenceIds = item["evidenceIds"];
534
+ if (!Array.isArray(item_evidenceIds) ||
535
+ item_evidenceIds.length < 1 ||
536
+ item_evidenceIds.length > 5)
537
+ return "recommendation_evidence_ids";
538
+ for (const item of item_evidenceIds) {
539
+ if (typeof item !== "string" ||
540
+ item.length < 1 ||
541
+ item.length > 128 ||
542
+ item.trim().length === 0)
543
+ return "recommendation_evidence_ids";
544
+ }
545
+ }
546
+ const value_documentationGaps = value["documentationGaps"];
547
+ if (!Array.isArray(value_documentationGaps) ||
548
+ value_documentationGaps.length > 20)
549
+ return "documentation_gaps";
550
+ for (const item of value_documentationGaps) {
551
+ if (typeof item !== "string" ||
552
+ item.length < 1 ||
553
+ item.length > 1000 ||
554
+ item.trim().length === 0)
555
+ return "documentation_gaps";
556
+ }
557
+ if (value["disposition"] === "review_required") {
558
+ if (!Array.isArray(value["recommendations"]) ||
559
+ value["recommendations"].length === 0)
560
+ return "review_required_recommendations";
561
+ }
562
+ else {
563
+ if (Array.isArray(value["recommendations"]) &&
564
+ value["recommendations"].length > 0)
565
+ return "disposition_recommendations";
566
+ }
567
+ if (options?.allowedReferenceIds) {
568
+ for (const recommendation of value["recommendations"] ?? []) {
569
+ const rec = isRecord(recommendation) ? recommendation : {};
570
+ const ids = Array.isArray(rec["evidenceIds"])
571
+ ? rec["evidenceIds"]
572
+ : [];
573
+ for (const id of ids) {
574
+ if (!options.allowedReferenceIds.has(String(id)))
575
+ return "recommendation_unapproved_evidence";
576
+ }
577
+ }
578
+ }
579
+ if (options?.referenceTextById) {
580
+ for (const recommendation of value["recommendations"] ?? []) {
581
+ const rec = isRecord(recommendation) ? recommendation : {};
582
+ const ids = Array.isArray(rec["evidenceIds"])
583
+ ? rec["evidenceIds"]
584
+ : [];
585
+ if (ids.length === 0)
586
+ continue;
587
+ const code = String(rec["code"] ?? "");
588
+ const codePattern = new RegExp("(?<![A-Za-z0-9.])" +
589
+ escapeRegExp(code) +
590
+ "(?![A-Za-z0-9]|\\.[A-Za-z0-9])", "i");
591
+ if (!ids.some((id) => codePattern.test(options.referenceTextById?.[String(id)] ?? "")))
592
+ return "recommendation_code_not_in_evidence";
593
+ }
594
+ }
595
+ return null;
596
+ }
597
+ const validRcmCodingOutput = (value) => rcmCodingOutputValidationError(value) === null;
598
+ exports.validRcmCodingOutput = validRcmCodingOutput;
599
+ exports.RcmCodingOutputSchemaJson = {
600
+ $schema: "https://json-schema.org/draft/2020-12/schema",
601
+ $id: "https://nexalink.care/contracts/rcm-coding-output.schema.json",
602
+ title: "RcmCodingOutput",
603
+ description: "Grounded RCM coding-review result returned by the hosted runtime. This is the stable compatibility contract behind the legacy rcm-grounded-human-review-v2 output schema version. The runtime postcondition fails closed: any structural or grounding violation is replaced with an escalate response carrying rcm_validation_error.",
604
+ version: "1.0.0",
605
+ type: "object",
606
+ additionalProperties: false,
607
+ required: [
608
+ "disposition",
609
+ "humanReviewRequired",
610
+ "recommendations",
611
+ "documentationGaps",
612
+ "rationale",
613
+ ],
614
+ properties: {
615
+ disposition: {
616
+ type: "string",
617
+ enum: ["review_required", "abstain", "escalate"],
618
+ },
619
+ humanReviewRequired: {
620
+ type: "boolean",
621
+ const: true,
622
+ },
623
+ rationale: {
624
+ type: "string",
625
+ minLength: 1,
626
+ maxLength: 4000,
627
+ },
628
+ recommendations: {
629
+ type: "array",
630
+ maxItems: 20,
631
+ items: {
632
+ type: "object",
633
+ additionalProperties: false,
634
+ required: [
635
+ "code",
636
+ "codeSystem",
637
+ "confidence",
638
+ "rationale",
639
+ "evidenceIds",
640
+ ],
641
+ properties: {
642
+ code: {
643
+ type: "string",
644
+ minLength: 1,
645
+ maxLength: 64,
646
+ },
647
+ codeSystem: {
648
+ type: "string",
649
+ enum: ["ICD-10-CM", "CPT", "HCPCS"],
650
+ },
651
+ confidence: {
652
+ type: "string",
653
+ enum: ["low", "medium", "high"],
654
+ },
655
+ rationale: {
656
+ type: "string",
657
+ minLength: 1,
658
+ maxLength: 2000,
659
+ },
660
+ evidenceIds: {
661
+ type: "array",
662
+ minItems: 1,
663
+ maxItems: 5,
664
+ items: {
665
+ type: "string",
666
+ minLength: 1,
667
+ maxLength: 128,
668
+ },
669
+ },
670
+ },
671
+ },
672
+ },
673
+ documentationGaps: {
674
+ type: "array",
675
+ maxItems: 20,
676
+ items: {
677
+ type: "string",
678
+ minLength: 1,
679
+ maxLength: 1000,
680
+ },
681
+ },
682
+ },
683
+ if: {
684
+ properties: {
685
+ disposition: {
686
+ const: "review_required",
687
+ },
688
+ },
689
+ required: ["disposition"],
690
+ },
691
+ then: {
692
+ properties: {
693
+ recommendations: {
694
+ minItems: 1,
695
+ },
696
+ },
697
+ },
698
+ else: {
699
+ properties: {
700
+ recommendations: {
701
+ maxItems: 0,
702
+ },
703
+ },
704
+ },
705
+ };
706
+ // --------------------------------------------------------------------
707
+ // RcmModelPrompt (schema 1.0.0, wire rcm-model-prompt-v1)
708
+ // --------------------------------------------------------------------
709
+ exports.rcmModelPromptSchema = zod_1.z
710
+ .object({
711
+ encounter: zod_1.z
712
+ .object({
713
+ encounterId: zod_1.z.string().min(1).max(160),
714
+ diagnosisNarrative: zod_1.z.string().min(1).max(2000),
715
+ procedureNarrative: zod_1.z.string().max(2000).optional(),
716
+ serviceDate: zod_1.z
717
+ .string()
718
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}$"))
719
+ .optional(),
720
+ placeOfService: zod_1.z.string().min(1).max(20).optional(),
721
+ claimContext: zod_1.z
722
+ .object({
723
+ stage: zod_1.z.enum(["development", "staging", "production"]).optional(),
724
+ payerName: zod_1.z.string().min(1).max(160).optional(),
725
+ submittedCodes: zod_1.z
726
+ .array(zod_1.z.string().min(1).max(20))
727
+ .max(20)
728
+ .optional(),
729
+ })
730
+ .strict()
731
+ .optional(),
732
+ })
733
+ .strict(),
734
+ supportingReferences: zod_1.z.array(exports.rcmSupportingReferenceSchema).max(5),
735
+ })
736
+ .strict();
737
+ function rcmModelPromptValidationError(value) {
738
+ if (!isRecord(value))
739
+ return "model_prompt";
740
+ if (!Object.keys(value).every((key) => ["encounter", "supportingReferences"].includes(key)) ||
741
+ !["encounter", "supportingReferences"].every((key) => key in value))
742
+ return "model_prompt_keys";
743
+ const value_encounter = value["encounter"];
744
+ if (!isRecord(value_encounter))
745
+ return "encounter";
746
+ if (!Object.keys(value_encounter).every((key) => [
747
+ "encounterId",
748
+ "diagnosisNarrative",
749
+ "procedureNarrative",
750
+ "serviceDate",
751
+ "placeOfService",
752
+ "claimContext",
753
+ ].includes(key)) ||
754
+ !["encounterId", "diagnosisNarrative"].every((key) => key in value_encounter))
755
+ return "encounter_keys";
756
+ const value_encounter_encounterId = value_encounter["encounterId"];
757
+ if (typeof value_encounter_encounterId !== "string" ||
758
+ value_encounter_encounterId.length < 1 ||
759
+ value_encounter_encounterId.length > 160)
760
+ return "encounter_id";
761
+ const value_encounter_diagnosisNarrative = value_encounter["diagnosisNarrative"];
762
+ if (typeof value_encounter_diagnosisNarrative !== "string" ||
763
+ value_encounter_diagnosisNarrative.length < 1 ||
764
+ value_encounter_diagnosisNarrative.length > 2000)
765
+ return "diagnosis_narrative";
766
+ if (value_encounter["procedureNarrative"] !== undefined) {
767
+ const value_encounter_procedureNarrative = value_encounter["procedureNarrative"];
768
+ if (typeof value_encounter_procedureNarrative !== "string" ||
769
+ value_encounter_procedureNarrative.length > 2000)
770
+ return "procedure_narrative";
771
+ }
772
+ if (value_encounter["serviceDate"] !== undefined) {
773
+ const value_encounter_serviceDate = value_encounter["serviceDate"];
774
+ if (typeof value_encounter_serviceDate !== "string" ||
775
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}$").test(value_encounter_serviceDate))
776
+ return "service_date";
777
+ }
778
+ if (value_encounter["placeOfService"] !== undefined) {
779
+ const value_encounter_placeOfService = value_encounter["placeOfService"];
780
+ if (typeof value_encounter_placeOfService !== "string" ||
781
+ value_encounter_placeOfService.length < 1 ||
782
+ value_encounter_placeOfService.length > 20)
783
+ return "place_of_service";
784
+ }
785
+ if (value_encounter["claimContext"] !== undefined) {
786
+ const value_encounter_claimContext = value_encounter["claimContext"];
787
+ if (!isRecord(value_encounter_claimContext))
788
+ return "claim_context";
789
+ if (!Object.keys(value_encounter_claimContext).every((key) => ["stage", "payerName", "submittedCodes"].includes(key)))
790
+ return "claim_context";
791
+ if (value_encounter_claimContext["stage"] !== undefined) {
792
+ const value_encounter_claimContext_stage = value_encounter_claimContext["stage"];
793
+ if (typeof value_encounter_claimContext_stage !== "string" ||
794
+ !["development", "staging", "production"].includes(value_encounter_claimContext_stage))
795
+ return "claim_context_stage";
796
+ }
797
+ if (value_encounter_claimContext["payerName"] !== undefined) {
798
+ const value_encounter_claimContext_payerName = value_encounter_claimContext["payerName"];
799
+ if (typeof value_encounter_claimContext_payerName !== "string" ||
800
+ value_encounter_claimContext_payerName.length < 1 ||
801
+ value_encounter_claimContext_payerName.length > 160)
802
+ return "claim_context_payer_name";
803
+ }
804
+ if (value_encounter_claimContext["submittedCodes"] !== undefined) {
805
+ const value_encounter_claimContext_submittedCodes = value_encounter_claimContext["submittedCodes"];
806
+ if (!Array.isArray(value_encounter_claimContext_submittedCodes) ||
807
+ value_encounter_claimContext_submittedCodes.length > 20)
808
+ return "claim_context_submitted_codes";
809
+ for (const item of value_encounter_claimContext_submittedCodes) {
810
+ if (typeof item !== "string" || item.length < 1 || item.length > 20)
811
+ return "claim_context_submitted_codes";
812
+ }
813
+ }
814
+ }
815
+ const value_supportingReferences = value["supportingReferences"];
816
+ if (!Array.isArray(value_supportingReferences) ||
817
+ value_supportingReferences.length > 5)
818
+ return "model_prompt_references";
819
+ for (const item of value_supportingReferences) {
820
+ const itemError = rcmSupportingReferenceValidationError(item);
821
+ if (itemError !== null)
822
+ return itemError;
823
+ }
824
+ return null;
825
+ }
826
+ const validRcmModelPrompt = (value) => rcmModelPromptValidationError(value) === null;
827
+ exports.validRcmModelPrompt = validRcmModelPrompt;
828
+ exports.RcmModelPromptSchemaJson = {
829
+ $schema: "https://json-schema.org/draft/2020-12/schema",
830
+ $id: "https://nexalink.care/contracts/rcm-model-prompt.schema.json",
831
+ title: "RcmModelPrompt",
832
+ description: "Structured JSON presented to the coding model. The encounter carries the request case fields and supportingReferences carry server-resolved or development-approved evidence. The hosted runtime builds this itself from retrieval and never accepts caller-supplied references outside development.",
833
+ version: "1.0.0",
834
+ type: "object",
835
+ additionalProperties: false,
836
+ required: ["encounter", "supportingReferences"],
837
+ properties: {
838
+ encounter: {
839
+ type: "object",
840
+ additionalProperties: false,
841
+ required: ["encounterId", "diagnosisNarrative"],
842
+ properties: {
843
+ encounterId: {
844
+ type: "string",
845
+ minLength: 1,
846
+ maxLength: 160,
847
+ },
848
+ diagnosisNarrative: {
849
+ type: "string",
850
+ minLength: 1,
851
+ maxLength: 2000,
852
+ },
853
+ procedureNarrative: {
854
+ type: "string",
855
+ maxLength: 2000,
856
+ },
857
+ serviceDate: {
858
+ type: "string",
859
+ pattern: "^\\d{4}-\\d{2}-\\d{2}$",
860
+ },
861
+ placeOfService: {
862
+ type: "string",
863
+ minLength: 1,
864
+ maxLength: 20,
865
+ },
866
+ claimContext: {
867
+ type: "object",
868
+ additionalProperties: false,
869
+ properties: {
870
+ stage: {
871
+ type: "string",
872
+ enum: ["development", "staging", "production"],
873
+ },
874
+ payerName: {
875
+ type: "string",
876
+ minLength: 1,
877
+ maxLength: 160,
878
+ },
879
+ submittedCodes: {
880
+ type: "array",
881
+ maxItems: 20,
882
+ items: {
883
+ type: "string",
884
+ minLength: 1,
885
+ maxLength: 20,
886
+ },
887
+ },
888
+ },
889
+ },
890
+ },
891
+ },
892
+ supportingReferences: {
893
+ type: "array",
894
+ maxItems: 5,
895
+ items: {
896
+ $ref: "rcm-supporting-reference.schema.json",
897
+ },
898
+ },
899
+ },
900
+ };
901
+ // --------------------------------------------------------------------
902
+ // RcmRetrievalMetadata (schema 1.0.0, wire rcm-retrieval-metadata-v1)
903
+ // --------------------------------------------------------------------
904
+ exports.rcmRetrievalMetadataSchema = zod_1.z
905
+ .object({
906
+ corpusId: zod_1.z.string().min(1).max(128),
907
+ corpusVersion: zod_1.z.string().min(1).max(128),
908
+ outcome: zod_1.z.enum(["completed", "empty", "failed"]),
909
+ latencyMs: zod_1.z.number().int().min(0),
910
+ knowledgeBaseId: zod_1.z.string().max(128).optional(),
911
+ tenantId: zod_1.z.string().max(128).optional(),
912
+ references: zod_1.z.array(exports.rcmSupportingReferenceSchema),
913
+ })
914
+ .strict();
915
+ function rcmRetrievalMetadataValidationError(value) {
916
+ if (!isRecord(value))
917
+ return "retrieval_metadata";
918
+ if (!Object.keys(value).every((key) => [
919
+ "corpusId",
920
+ "corpusVersion",
921
+ "outcome",
922
+ "latencyMs",
923
+ "knowledgeBaseId",
924
+ "tenantId",
925
+ "references",
926
+ ].includes(key)) ||
927
+ !["corpusId", "corpusVersion", "outcome", "latencyMs", "references"].every((key) => key in value))
928
+ return "retrieval_metadata_keys";
929
+ const value_corpusId = value["corpusId"];
930
+ if (typeof value_corpusId !== "string" ||
931
+ value_corpusId.length < 1 ||
932
+ value_corpusId.length > 128)
933
+ return "corpus_id";
934
+ const value_corpusVersion = value["corpusVersion"];
935
+ if (typeof value_corpusVersion !== "string" ||
936
+ value_corpusVersion.length < 1 ||
937
+ value_corpusVersion.length > 128)
938
+ return "corpus_version";
939
+ const value_outcome = value["outcome"];
940
+ if (typeof value_outcome !== "string" ||
941
+ !["completed", "empty", "failed"].includes(value_outcome))
942
+ return "retrieval_outcome";
943
+ const value_latencyMs = value["latencyMs"];
944
+ if (typeof value_latencyMs !== "number" ||
945
+ Number.isNaN(value_latencyMs) ||
946
+ !Number.isInteger(value_latencyMs) ||
947
+ value_latencyMs < 0)
948
+ return "retrieval_latency_ms";
949
+ if (value["knowledgeBaseId"] !== undefined) {
950
+ const value_knowledgeBaseId = value["knowledgeBaseId"];
951
+ if (typeof value_knowledgeBaseId !== "string" ||
952
+ value_knowledgeBaseId.length > 128)
953
+ return "knowledge_base_id";
954
+ }
955
+ if (value["tenantId"] !== undefined) {
956
+ const value_tenantId = value["tenantId"];
957
+ if (typeof value_tenantId !== "string" || value_tenantId.length > 128)
958
+ return "retrieval_tenant_id";
959
+ }
960
+ const value_references = value["references"];
961
+ if (!Array.isArray(value_references))
962
+ return "retrieval_references";
963
+ for (const item of value_references) {
964
+ const itemError = rcmSupportingReferenceValidationError(item);
965
+ if (itemError !== null)
966
+ return itemError;
967
+ }
968
+ return null;
969
+ }
970
+ const validRcmRetrievalMetadata = (value) => rcmRetrievalMetadataValidationError(value) === null;
971
+ exports.validRcmRetrievalMetadata = validRcmRetrievalMetadata;
972
+ exports.RcmRetrievalMetadataSchemaJson = {
973
+ $schema: "https://json-schema.org/draft/2020-12/schema",
974
+ $id: "https://nexalink.care/contracts/rcm-retrieval-metadata.schema.json",
975
+ title: "RcmRetrievalMetadata",
976
+ description: "Bounded metadata attached to a hosted RCM retrieval outcome. The client-visible shape omits tenantId and knowledgeBaseId; both are included here as optional so the full runtime envelope and the persisted client-facing metadata validate against the same contract.",
977
+ version: "1.0.0",
978
+ type: "object",
979
+ additionalProperties: false,
980
+ required: ["corpusId", "corpusVersion", "outcome", "latencyMs", "references"],
981
+ properties: {
982
+ corpusId: {
983
+ type: "string",
984
+ minLength: 1,
985
+ maxLength: 128,
986
+ },
987
+ corpusVersion: {
988
+ type: "string",
989
+ minLength: 1,
990
+ maxLength: 128,
991
+ },
992
+ outcome: {
993
+ type: "string",
994
+ enum: ["completed", "empty", "failed"],
995
+ },
996
+ latencyMs: {
997
+ type: "integer",
998
+ minimum: 0,
999
+ },
1000
+ knowledgeBaseId: {
1001
+ type: "string",
1002
+ maxLength: 128,
1003
+ },
1004
+ tenantId: {
1005
+ type: "string",
1006
+ maxLength: 128,
1007
+ },
1008
+ references: {
1009
+ type: "array",
1010
+ items: {
1011
+ $ref: "rcm-supporting-reference.schema.json",
1012
+ },
1013
+ },
1014
+ },
1015
+ };
1016
+ // --------------------------------------------------------------------
1017
+ // RcmRuntimeEvent (schema 1.0.0, wire rcm-runtime-event-v1)
1018
+ // --------------------------------------------------------------------
1019
+ exports.rcmRuntimeEventSchema = zod_1.z
1020
+ .object({
1021
+ type: zod_1.z.enum(["audit", "safety"]),
1022
+ outcome: zod_1.z.enum(["authorized", "validated", "escalated"]),
1023
+ reason: zod_1.z.enum([
1024
+ "workflow_authorized",
1025
+ "output_validated",
1026
+ "output_invalid",
1027
+ "workflow_escalated",
1028
+ "guardrail_blocked",
1029
+ "retrieval_completed",
1030
+ "retrieval_failed",
1031
+ ]),
1032
+ occurredAt: zod_1.z
1033
+ .string()
1034
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}"))
1035
+ .max(64),
1036
+ workflowId: zod_1.z.enum(["rcm-coding-assistance"]),
1037
+ guardrail: zod_1.z
1038
+ .object({
1039
+ stopReason: zod_1.z.string().max(64).optional(),
1040
+ actions: zod_1.z
1041
+ .array(zod_1.z
1042
+ .object({
1043
+ scope: zod_1.z.string().max(64),
1044
+ policyType: zod_1.z.string().max(64),
1045
+ rule: zod_1.z.string().max(128),
1046
+ action: zod_1.z.string().max(64),
1047
+ })
1048
+ .strict())
1049
+ .optional(),
1050
+ })
1051
+ .strict()
1052
+ .optional(),
1053
+ retrieval: zod_1.z
1054
+ .object({
1055
+ corpusId: zod_1.z.string().min(1).max(128),
1056
+ corpusVersion: zod_1.z.string().min(1).max(128),
1057
+ outcome: zod_1.z.string().max(64),
1058
+ referenceCount: zod_1.z.number().int().min(0),
1059
+ latencyMs: zod_1.z.number().int().min(0),
1060
+ references: zod_1.z.array(zod_1.z
1061
+ .object({
1062
+ referenceId: zod_1.z
1063
+ .string()
1064
+ .regex(new RegExp("^reference-[1-9][0-9]*$"))
1065
+ .max(32),
1066
+ documentId: zod_1.z.string().min(1).max(240),
1067
+ version: zod_1.z.string().min(1).max(80),
1068
+ })
1069
+ .strict()),
1070
+ })
1071
+ .strict()
1072
+ .optional(),
1073
+ })
1074
+ .strict();
1075
+ function rcmRuntimeEventValidationError(value) {
1076
+ if (!isRecord(value))
1077
+ return "runtime_event";
1078
+ if (!Object.keys(value).every((key) => [
1079
+ "type",
1080
+ "outcome",
1081
+ "reason",
1082
+ "occurredAt",
1083
+ "workflowId",
1084
+ "guardrail",
1085
+ "retrieval",
1086
+ ].includes(key)) ||
1087
+ !["type", "outcome", "reason", "occurredAt", "workflowId"].every((key) => key in value))
1088
+ return "runtime_event_keys";
1089
+ const value_type = value["type"];
1090
+ if (typeof value_type !== "string" ||
1091
+ !["audit", "safety"].includes(value_type))
1092
+ return "runtime_event_type";
1093
+ const value_outcome = value["outcome"];
1094
+ if (typeof value_outcome !== "string" ||
1095
+ !["authorized", "validated", "escalated"].includes(value_outcome))
1096
+ return "runtime_event_outcome";
1097
+ const value_reason = value["reason"];
1098
+ if (typeof value_reason !== "string" ||
1099
+ ![
1100
+ "workflow_authorized",
1101
+ "output_validated",
1102
+ "output_invalid",
1103
+ "workflow_escalated",
1104
+ "guardrail_blocked",
1105
+ "retrieval_completed",
1106
+ "retrieval_failed",
1107
+ ].includes(value_reason))
1108
+ return "runtime_event_reason";
1109
+ const value_occurredAt = value["occurredAt"];
1110
+ if (typeof value_occurredAt !== "string" ||
1111
+ value_occurredAt.length > 64 ||
1112
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}").test(value_occurredAt))
1113
+ return "runtime_event_occurred_at";
1114
+ const value_workflowId = value["workflowId"];
1115
+ if (typeof value_workflowId !== "string" ||
1116
+ !["rcm-coding-assistance"].includes(value_workflowId))
1117
+ return "runtime_event_workflow_id";
1118
+ if (value["guardrail"] !== undefined) {
1119
+ const value_guardrail = value["guardrail"];
1120
+ if (!isRecord(value_guardrail))
1121
+ return "runtime_event_guardrail";
1122
+ if (!Object.keys(value_guardrail).every((key) => ["stopReason", "actions"].includes(key)))
1123
+ return "runtime_event_guardrail_keys";
1124
+ if (value_guardrail["stopReason"] !== undefined) {
1125
+ const value_guardrail_stopReason = value_guardrail["stopReason"];
1126
+ if (typeof value_guardrail_stopReason !== "string" ||
1127
+ value_guardrail_stopReason.length > 64)
1128
+ return "runtime_event_guardrail_stop_reason";
1129
+ }
1130
+ if (value_guardrail["actions"] !== undefined) {
1131
+ const value_guardrail_actions = value_guardrail["actions"];
1132
+ if (!Array.isArray(value_guardrail_actions))
1133
+ return "runtime_event_guardrail_actions";
1134
+ for (const item of value_guardrail_actions) {
1135
+ if (!isRecord(item))
1136
+ 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))
1139
+ return "runtime_event_guardrail_action_keys";
1140
+ const item_scope = item["scope"];
1141
+ if (typeof item_scope !== "string" || item_scope.length > 64)
1142
+ return "runtime_event_guardrail_action_scope";
1143
+ const item_policyType = item["policyType"];
1144
+ if (typeof item_policyType !== "string" || item_policyType.length > 64)
1145
+ return "runtime_event_guardrail_action_policy_type";
1146
+ const item_rule = item["rule"];
1147
+ if (typeof item_rule !== "string" || item_rule.length > 128)
1148
+ return "runtime_event_guardrail_action_rule";
1149
+ const item_action = item["action"];
1150
+ if (typeof item_action !== "string" || item_action.length > 64)
1151
+ return "runtime_event_guardrail_action_type";
1152
+ }
1153
+ }
1154
+ }
1155
+ if (value["retrieval"] !== undefined) {
1156
+ const value_retrieval = value["retrieval"];
1157
+ if (!isRecord(value_retrieval))
1158
+ return "runtime_event_retrieval";
1159
+ if (!Object.keys(value_retrieval).every((key) => [
1160
+ "corpusId",
1161
+ "corpusVersion",
1162
+ "outcome",
1163
+ "referenceCount",
1164
+ "latencyMs",
1165
+ "references",
1166
+ ].includes(key)) ||
1167
+ ![
1168
+ "corpusId",
1169
+ "corpusVersion",
1170
+ "outcome",
1171
+ "referenceCount",
1172
+ "latencyMs",
1173
+ "references",
1174
+ ].every((key) => key in value_retrieval))
1175
+ return "runtime_event_retrieval_keys";
1176
+ const value_retrieval_corpusId = value_retrieval["corpusId"];
1177
+ if (typeof value_retrieval_corpusId !== "string" ||
1178
+ value_retrieval_corpusId.length < 1 ||
1179
+ value_retrieval_corpusId.length > 128)
1180
+ return "runtime_event_retrieval_corpus_id";
1181
+ const value_retrieval_corpusVersion = value_retrieval["corpusVersion"];
1182
+ if (typeof value_retrieval_corpusVersion !== "string" ||
1183
+ value_retrieval_corpusVersion.length < 1 ||
1184
+ value_retrieval_corpusVersion.length > 128)
1185
+ return "runtime_event_retrieval_corpus_version";
1186
+ const value_retrieval_outcome = value_retrieval["outcome"];
1187
+ if (typeof value_retrieval_outcome !== "string" ||
1188
+ value_retrieval_outcome.length > 64)
1189
+ return "runtime_event_retrieval_outcome";
1190
+ const value_retrieval_referenceCount = value_retrieval["referenceCount"];
1191
+ if (typeof value_retrieval_referenceCount !== "number" ||
1192
+ Number.isNaN(value_retrieval_referenceCount) ||
1193
+ !Number.isInteger(value_retrieval_referenceCount) ||
1194
+ value_retrieval_referenceCount < 0)
1195
+ return "runtime_event_retrieval_reference_count";
1196
+ const value_retrieval_latencyMs = value_retrieval["latencyMs"];
1197
+ if (typeof value_retrieval_latencyMs !== "number" ||
1198
+ Number.isNaN(value_retrieval_latencyMs) ||
1199
+ !Number.isInteger(value_retrieval_latencyMs) ||
1200
+ value_retrieval_latencyMs < 0)
1201
+ return "runtime_event_retrieval_latency_ms";
1202
+ const value_retrieval_references = value_retrieval["references"];
1203
+ if (!Array.isArray(value_retrieval_references))
1204
+ return "runtime_event_retrieval_references";
1205
+ for (const item of value_retrieval_references) {
1206
+ if (!isRecord(item))
1207
+ 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))
1210
+ return "runtime_event_retrieval_reference_keys";
1211
+ const item_referenceId = item["referenceId"];
1212
+ if (typeof item_referenceId !== "string" ||
1213
+ item_referenceId.length > 32 ||
1214
+ !new RegExp("^reference-[1-9][0-9]*$").test(item_referenceId))
1215
+ return "runtime_event_retrieval_reference_id";
1216
+ const item_documentId = item["documentId"];
1217
+ if (typeof item_documentId !== "string" ||
1218
+ item_documentId.length < 1 ||
1219
+ item_documentId.length > 240)
1220
+ return "runtime_event_retrieval_document_id";
1221
+ const item_version = item["version"];
1222
+ if (typeof item_version !== "string" ||
1223
+ item_version.length < 1 ||
1224
+ item_version.length > 80)
1225
+ return "runtime_event_retrieval_reference_version";
1226
+ }
1227
+ }
1228
+ return null;
1229
+ }
1230
+ const validRcmRuntimeEvent = (value) => rcmRuntimeEventValidationError(value) === null;
1231
+ exports.validRcmRuntimeEvent = validRcmRuntimeEvent;
1232
+ exports.RcmRuntimeEventSchemaJson = {
1233
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1234
+ $id: "https://nexalink.care/contracts/rcm-runtime-event.schema.json",
1235
+ title: "RcmRuntimeEvent",
1236
+ description: "Sanitized audit or safety event emitted along a workflow runtime lifecycle. Events never carry prompts, raw PHI, or unrestricted guardrail trace content.",
1237
+ version: "1.0.0",
1238
+ type: "object",
1239
+ additionalProperties: false,
1240
+ required: ["type", "outcome", "reason", "occurredAt", "workflowId"],
1241
+ properties: {
1242
+ type: {
1243
+ type: "string",
1244
+ enum: ["audit", "safety"],
1245
+ },
1246
+ outcome: {
1247
+ type: "string",
1248
+ enum: ["authorized", "validated", "escalated"],
1249
+ },
1250
+ reason: {
1251
+ type: "string",
1252
+ enum: [
1253
+ "workflow_authorized",
1254
+ "output_validated",
1255
+ "output_invalid",
1256
+ "workflow_escalated",
1257
+ "guardrail_blocked",
1258
+ "retrieval_completed",
1259
+ "retrieval_failed",
1260
+ ],
1261
+ },
1262
+ occurredAt: {
1263
+ type: "string",
1264
+ pattern: "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}",
1265
+ maxLength: 64,
1266
+ },
1267
+ workflowId: {
1268
+ type: "string",
1269
+ enum: ["rcm-coding-assistance"],
1270
+ },
1271
+ guardrail: {
1272
+ type: "object",
1273
+ additionalProperties: false,
1274
+ properties: {
1275
+ stopReason: {
1276
+ type: "string",
1277
+ maxLength: 64,
1278
+ },
1279
+ actions: {
1280
+ type: "array",
1281
+ items: {
1282
+ type: "object",
1283
+ additionalProperties: false,
1284
+ required: ["scope", "policyType", "rule", "action"],
1285
+ properties: {
1286
+ scope: {
1287
+ type: "string",
1288
+ maxLength: 64,
1289
+ },
1290
+ policyType: {
1291
+ type: "string",
1292
+ maxLength: 64,
1293
+ },
1294
+ rule: {
1295
+ type: "string",
1296
+ maxLength: 128,
1297
+ },
1298
+ action: {
1299
+ type: "string",
1300
+ maxLength: 64,
1301
+ },
1302
+ },
1303
+ },
1304
+ },
1305
+ },
1306
+ },
1307
+ retrieval: {
1308
+ type: "object",
1309
+ additionalProperties: false,
1310
+ required: [
1311
+ "corpusId",
1312
+ "corpusVersion",
1313
+ "outcome",
1314
+ "referenceCount",
1315
+ "latencyMs",
1316
+ "references",
1317
+ ],
1318
+ properties: {
1319
+ corpusId: {
1320
+ type: "string",
1321
+ minLength: 1,
1322
+ maxLength: 128,
1323
+ },
1324
+ corpusVersion: {
1325
+ type: "string",
1326
+ minLength: 1,
1327
+ maxLength: 128,
1328
+ },
1329
+ outcome: {
1330
+ type: "string",
1331
+ maxLength: 64,
1332
+ },
1333
+ referenceCount: {
1334
+ type: "integer",
1335
+ minimum: 0,
1336
+ },
1337
+ latencyMs: {
1338
+ type: "integer",
1339
+ minimum: 0,
1340
+ },
1341
+ references: {
1342
+ type: "array",
1343
+ items: {
1344
+ type: "object",
1345
+ additionalProperties: false,
1346
+ required: ["referenceId", "documentId", "version"],
1347
+ properties: {
1348
+ referenceId: {
1349
+ type: "string",
1350
+ pattern: "^reference-[1-9][0-9]*$",
1351
+ maxLength: 32,
1352
+ },
1353
+ documentId: {
1354
+ type: "string",
1355
+ minLength: 1,
1356
+ maxLength: 240,
1357
+ },
1358
+ version: {
1359
+ type: "string",
1360
+ minLength: 1,
1361
+ maxLength: 80,
1362
+ },
1363
+ },
1364
+ },
1365
+ },
1366
+ },
1367
+ },
1368
+ },
1369
+ };
1370
+ // --------------------------------------------------------------------
1371
+ // RcmWorkflowCatalog (schema 1.0.0, wire rcm-workflow-catalog-v1)
1372
+ // --------------------------------------------------------------------
1373
+ exports.rcmWorkflowCatalogSchema = zod_1.z
1374
+ .object({
1375
+ id: zod_1.z.enum(["rcm-coding-assistance"]),
1376
+ name: zod_1.z.string().min(1).max(120),
1377
+ description: zod_1.z.string().min(1).max(400),
1378
+ environments: zod_1.z.array(zod_1.z.enum(["development", "production"])).min(1),
1379
+ modelPolicy: zod_1.z
1380
+ .object({
1381
+ policyId: zod_1.z.literal("carecompass-rcm-review-v1"),
1382
+ inferencePath: zod_1.z.string().max(64),
1383
+ maxNewTokens: zod_1.z.number().int().min(1).max(2048),
1384
+ temperature: zod_1.z.number().min(0).max(2),
1385
+ outputSchemaVersion: zod_1.z.literal("rcm-grounded-human-review-v2"),
1386
+ requireHumanReview: zod_1.z.literal(true),
1387
+ })
1388
+ .strict(),
1389
+ humanReviewPolicy: zod_1.z
1390
+ .object({
1391
+ policyId: zod_1.z.literal("qualified-coder-review-v1"),
1392
+ humanReviewRequired: zod_1.z.literal(true),
1393
+ })
1394
+ .strict(),
1395
+ outputSchemaVersion: zod_1.z.literal("rcm-grounded-human-review-v2"),
1396
+ })
1397
+ .strict();
1398
+ function rcmWorkflowCatalogValidationError(value) {
1399
+ if (!isRecord(value))
1400
+ return "workflow_catalog";
1401
+ if (!Object.keys(value).every((key) => [
1402
+ "id",
1403
+ "name",
1404
+ "description",
1405
+ "environments",
1406
+ "modelPolicy",
1407
+ "humanReviewPolicy",
1408
+ "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))
1419
+ return "workflow_catalog_keys";
1420
+ const value_id = value["id"];
1421
+ if (typeof value_id !== "string" ||
1422
+ !["rcm-coding-assistance"].includes(value_id))
1423
+ return "workflow_id";
1424
+ const value_name = value["name"];
1425
+ if (typeof value_name !== "string" ||
1426
+ value_name.length < 1 ||
1427
+ value_name.length > 120)
1428
+ return "workflow_name";
1429
+ const value_description = value["description"];
1430
+ if (typeof value_description !== "string" ||
1431
+ value_description.length < 1 ||
1432
+ value_description.length > 400)
1433
+ return "workflow_description";
1434
+ const value_environments = value["environments"];
1435
+ if (!Array.isArray(value_environments) || value_environments.length < 1)
1436
+ return "workflow_environments";
1437
+ for (const item of value_environments) {
1438
+ if (typeof item !== "string" ||
1439
+ !["development", "production"].includes(item))
1440
+ return "workflow_environment";
1441
+ }
1442
+ const value_modelPolicy = value["modelPolicy"];
1443
+ if (!isRecord(value_modelPolicy))
1444
+ return "model_policy";
1445
+ if (!Object.keys(value_modelPolicy).every((key) => [
1446
+ "policyId",
1447
+ "inferencePath",
1448
+ "maxNewTokens",
1449
+ "temperature",
1450
+ "outputSchemaVersion",
1451
+ "requireHumanReview",
1452
+ ].includes(key)) ||
1453
+ ![
1454
+ "policyId",
1455
+ "inferencePath",
1456
+ "maxNewTokens",
1457
+ "temperature",
1458
+ "outputSchemaVersion",
1459
+ "requireHumanReview",
1460
+ ].every((key) => key in value_modelPolicy))
1461
+ return "model_policy_keys";
1462
+ const value_modelPolicy_policyId = value_modelPolicy["policyId"];
1463
+ if (typeof value_modelPolicy_policyId !== "string" ||
1464
+ value_modelPolicy_policyId !== "carecompass-rcm-review-v1")
1465
+ return "model_policy_id";
1466
+ const value_modelPolicy_inferencePath = value_modelPolicy["inferencePath"];
1467
+ if (typeof value_modelPolicy_inferencePath !== "string" ||
1468
+ value_modelPolicy_inferencePath.length > 64)
1469
+ return "model_policy_inference_path";
1470
+ const value_modelPolicy_maxNewTokens = value_modelPolicy["maxNewTokens"];
1471
+ if (typeof value_modelPolicy_maxNewTokens !== "number" ||
1472
+ Number.isNaN(value_modelPolicy_maxNewTokens) ||
1473
+ !Number.isInteger(value_modelPolicy_maxNewTokens) ||
1474
+ value_modelPolicy_maxNewTokens < 1 ||
1475
+ value_modelPolicy_maxNewTokens > 2048)
1476
+ return "model_policy_max_new_tokens";
1477
+ const value_modelPolicy_temperature = value_modelPolicy["temperature"];
1478
+ if (typeof value_modelPolicy_temperature !== "number" ||
1479
+ Number.isNaN(value_modelPolicy_temperature) ||
1480
+ value_modelPolicy_temperature < 0 ||
1481
+ value_modelPolicy_temperature > 2)
1482
+ return "model_policy_temperature";
1483
+ const value_modelPolicy_outputSchemaVersion = value_modelPolicy["outputSchemaVersion"];
1484
+ if (typeof value_modelPolicy_outputSchemaVersion !== "string" ||
1485
+ value_modelPolicy_outputSchemaVersion !== "rcm-grounded-human-review-v2")
1486
+ return "model_policy_output_schema_version";
1487
+ const value_modelPolicy_requireHumanReview = value_modelPolicy["requireHumanReview"];
1488
+ if (typeof value_modelPolicy_requireHumanReview !== "boolean" ||
1489
+ value_modelPolicy_requireHumanReview !== true)
1490
+ return "model_policy_require_human_review";
1491
+ const value_humanReviewPolicy = value["humanReviewPolicy"];
1492
+ if (!isRecord(value_humanReviewPolicy))
1493
+ 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))
1496
+ return "human_review_policy_keys";
1497
+ const value_humanReviewPolicy_policyId = value_humanReviewPolicy["policyId"];
1498
+ if (typeof value_humanReviewPolicy_policyId !== "string" ||
1499
+ value_humanReviewPolicy_policyId !== "qualified-coder-review-v1")
1500
+ return "human_review_policy_id";
1501
+ const value_humanReviewPolicy_humanReviewRequired = value_humanReviewPolicy["humanReviewRequired"];
1502
+ if (typeof value_humanReviewPolicy_humanReviewRequired !== "boolean" ||
1503
+ value_humanReviewPolicy_humanReviewRequired !== true)
1504
+ return "human_review_policy_required";
1505
+ const value_outputSchemaVersion = value["outputSchemaVersion"];
1506
+ if (typeof value_outputSchemaVersion !== "string" ||
1507
+ value_outputSchemaVersion !== "rcm-grounded-human-review-v2")
1508
+ return "workflow_output_schema_version";
1509
+ return null;
1510
+ }
1511
+ const validRcmWorkflowCatalog = (value) => rcmWorkflowCatalogValidationError(value) === null;
1512
+ exports.validRcmWorkflowCatalog = validRcmWorkflowCatalog;
1513
+ exports.RcmWorkflowCatalogSchemaJson = {
1514
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1515
+ $id: "https://nexalink.care/contracts/rcm-workflow-catalog.schema.json",
1516
+ title: "RcmWorkflowCatalog",
1517
+ description: "A single authorized workflow entry. The catalog pins the workflow identifier, model policy, human-review policy, and output schema version that the runtime and portal may offer for the RCM coding-assistance workflow. Customer configuration can never redefine these immutable server-side values.",
1518
+ version: "1.0.0",
1519
+ type: "object",
1520
+ additionalProperties: false,
1521
+ required: [
1522
+ "id",
1523
+ "name",
1524
+ "description",
1525
+ "environments",
1526
+ "modelPolicy",
1527
+ "humanReviewPolicy",
1528
+ "outputSchemaVersion",
1529
+ ],
1530
+ properties: {
1531
+ id: {
1532
+ type: "string",
1533
+ enum: ["rcm-coding-assistance"],
1534
+ },
1535
+ name: {
1536
+ type: "string",
1537
+ minLength: 1,
1538
+ maxLength: 120,
1539
+ },
1540
+ description: {
1541
+ type: "string",
1542
+ minLength: 1,
1543
+ maxLength: 400,
1544
+ },
1545
+ environments: {
1546
+ type: "array",
1547
+ minItems: 1,
1548
+ items: {
1549
+ type: "string",
1550
+ enum: ["development", "production"],
1551
+ },
1552
+ },
1553
+ modelPolicy: {
1554
+ type: "object",
1555
+ additionalProperties: false,
1556
+ required: [
1557
+ "policyId",
1558
+ "inferencePath",
1559
+ "maxNewTokens",
1560
+ "temperature",
1561
+ "outputSchemaVersion",
1562
+ "requireHumanReview",
1563
+ ],
1564
+ properties: {
1565
+ policyId: {
1566
+ type: "string",
1567
+ const: "carecompass-rcm-review-v1",
1568
+ },
1569
+ inferencePath: {
1570
+ type: "string",
1571
+ maxLength: 64,
1572
+ },
1573
+ maxNewTokens: {
1574
+ type: "integer",
1575
+ minimum: 1,
1576
+ maximum: 2048,
1577
+ },
1578
+ temperature: {
1579
+ type: "number",
1580
+ minimum: 0,
1581
+ maximum: 2,
1582
+ },
1583
+ outputSchemaVersion: {
1584
+ type: "string",
1585
+ const: "rcm-grounded-human-review-v2",
1586
+ },
1587
+ requireHumanReview: {
1588
+ type: "boolean",
1589
+ const: true,
1590
+ },
1591
+ },
1592
+ },
1593
+ humanReviewPolicy: {
1594
+ type: "object",
1595
+ additionalProperties: false,
1596
+ required: ["policyId", "humanReviewRequired"],
1597
+ properties: {
1598
+ policyId: {
1599
+ type: "string",
1600
+ const: "qualified-coder-review-v1",
1601
+ },
1602
+ humanReviewRequired: {
1603
+ type: "boolean",
1604
+ const: true,
1605
+ },
1606
+ },
1607
+ },
1608
+ outputSchemaVersion: {
1609
+ type: "string",
1610
+ const: "rcm-grounded-human-review-v2",
1611
+ },
1612
+ },
1613
+ };