@kya-os/mcp-i-core 1.2.2-canary.34 → 1.2.2-canary.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-test$colon$coverage.log +2443 -2161
- package/.turbo/turbo-test.log +2666 -0
- package/coverage/coverage-final.json +2 -2
- package/dist/services/access-control.service.d.ts.map +1 -1
- package/dist/services/access-control.service.js +35 -25
- package/dist/services/access-control.service.js.map +1 -1
- package/package.json +2 -2
- package/src/services/__tests__/access-control.proof-response-validation.test.ts +95 -84
- package/src/services/access-control.service.ts +82 -57
|
@@ -376,7 +376,7 @@ export class AccessControlApiService {
|
|
|
376
376
|
});
|
|
377
377
|
|
|
378
378
|
const responseText = await httpResponse.text();
|
|
379
|
-
|
|
379
|
+
|
|
380
380
|
// CRITICAL: Log raw response IMMEDIATELY before parsing/validation
|
|
381
381
|
// This will help us debug validation failures
|
|
382
382
|
console.error(`[AccessControl] 🔍 RAW API RESPONSE (before parsing):`, {
|
|
@@ -388,15 +388,17 @@ export class AccessControlApiService {
|
|
|
388
388
|
responseTextPreview: responseText.substring(0, 500),
|
|
389
389
|
fullResponseText: responseText, // Full response for debugging
|
|
390
390
|
});
|
|
391
|
-
|
|
391
|
+
|
|
392
392
|
const responseData = this.parseResponseJSON(httpResponse, responseText);
|
|
393
|
-
|
|
393
|
+
|
|
394
394
|
// Log parsed response immediately after parsing
|
|
395
395
|
console.error(`[AccessControl] 🔍 PARSED RESPONSE DATA:`, {
|
|
396
396
|
correlationId,
|
|
397
397
|
status: httpResponse.status,
|
|
398
398
|
responseDataType: typeof responseData,
|
|
399
|
-
responseDataKeys: Object.keys(
|
|
399
|
+
responseDataKeys: Object.keys(
|
|
400
|
+
(responseData as Record<string, unknown>) || {}
|
|
401
|
+
),
|
|
400
402
|
responseData: JSON.stringify(responseData, null, 2),
|
|
401
403
|
});
|
|
402
404
|
|
|
@@ -511,35 +513,49 @@ export class AccessControlApiService {
|
|
|
511
513
|
// Extract data and add success field if missing (for schema validation)
|
|
512
514
|
// CRITICAL: Ensure data is actually an object, not a string or other type
|
|
513
515
|
let dataToValidate: Record<string, unknown>;
|
|
514
|
-
if (typeof wrappedResponse.data ===
|
|
516
|
+
if (typeof wrappedResponse.data === "string") {
|
|
515
517
|
// If data is a string, parse it (shouldn't happen but defensive)
|
|
516
518
|
try {
|
|
517
|
-
dataToValidate = JSON.parse(wrappedResponse.data) as Record<
|
|
519
|
+
dataToValidate = JSON.parse(wrappedResponse.data) as Record<
|
|
520
|
+
string,
|
|
521
|
+
unknown
|
|
522
|
+
>;
|
|
518
523
|
} catch (parseError) {
|
|
519
524
|
throw new AgentShieldAPIError(
|
|
520
525
|
"invalid_response",
|
|
521
526
|
"Failed to parse response data",
|
|
522
|
-
{
|
|
527
|
+
{
|
|
528
|
+
parseError:
|
|
529
|
+
parseError instanceof Error
|
|
530
|
+
? parseError.message
|
|
531
|
+
: String(parseError),
|
|
532
|
+
}
|
|
523
533
|
);
|
|
524
534
|
}
|
|
525
|
-
} else if (
|
|
535
|
+
} else if (
|
|
536
|
+
typeof wrappedResponse.data === "object" &&
|
|
537
|
+
wrappedResponse.data !== null
|
|
538
|
+
) {
|
|
526
539
|
dataToValidate = wrappedResponse.data as Record<string, unknown>;
|
|
527
540
|
} else {
|
|
528
541
|
throw new AgentShieldAPIError(
|
|
529
542
|
"invalid_response",
|
|
530
543
|
"Response data is not an object",
|
|
531
|
-
{
|
|
544
|
+
{
|
|
545
|
+
dataType: typeof wrappedResponse.data,
|
|
546
|
+
data: wrappedResponse.data,
|
|
547
|
+
}
|
|
532
548
|
);
|
|
533
549
|
}
|
|
534
|
-
|
|
550
|
+
|
|
535
551
|
// CRITICAL: Log the actual data structure for debugging
|
|
536
552
|
console.error(`[AccessControl] 🔍 DATA OBJECT STRUCTURE:`, {
|
|
537
553
|
correlationId,
|
|
538
554
|
dataKeys: Object.keys(dataToValidate),
|
|
539
|
-
hasAccepted:
|
|
540
|
-
hasRejected:
|
|
541
|
-
hasOutcomes:
|
|
542
|
-
hasErrors:
|
|
555
|
+
hasAccepted: "accepted" in dataToValidate,
|
|
556
|
+
hasRejected: "rejected" in dataToValidate,
|
|
557
|
+
hasOutcomes: "outcomes" in dataToValidate,
|
|
558
|
+
hasErrors: "errors" in dataToValidate,
|
|
543
559
|
acceptedType: typeof dataToValidate.accepted,
|
|
544
560
|
acceptedValue: dataToValidate.accepted,
|
|
545
561
|
rejectedType: typeof dataToValidate.rejected,
|
|
@@ -550,7 +566,7 @@ export class AccessControlApiService {
|
|
|
550
566
|
errorsIsArray: Array.isArray(dataToValidate.errors),
|
|
551
567
|
fullData: JSON.stringify(dataToValidate, null, 2),
|
|
552
568
|
});
|
|
553
|
-
|
|
569
|
+
|
|
554
570
|
// Ensure success field is present (required by schema)
|
|
555
571
|
// wrappedResponse.success should be true since we checked it exists
|
|
556
572
|
// CRITICAL: Explicitly construct the object to ensure all fields are present
|
|
@@ -560,50 +576,59 @@ export class AccessControlApiService {
|
|
|
560
576
|
accepted: dataToValidate.accepted,
|
|
561
577
|
rejected: dataToValidate.rejected,
|
|
562
578
|
};
|
|
563
|
-
|
|
579
|
+
|
|
564
580
|
// Add optional fields if present
|
|
565
|
-
if (
|
|
581
|
+
if (
|
|
582
|
+
"outcomes" in dataToValidate &&
|
|
583
|
+
dataToValidate.outcomes !== undefined
|
|
584
|
+
) {
|
|
566
585
|
dataWithSuccess.outcomes = dataToValidate.outcomes;
|
|
567
586
|
}
|
|
568
|
-
if (
|
|
587
|
+
if ("errors" in dataToValidate && dataToValidate.errors !== undefined) {
|
|
569
588
|
dataWithSuccess.errors = dataToValidate.errors;
|
|
570
589
|
}
|
|
571
|
-
|
|
590
|
+
|
|
572
591
|
// CRITICAL: Log what we're validating
|
|
573
592
|
console.error(`[AccessControl] 🔍 VALIDATING DATA WITH SUCCESS:`, {
|
|
574
593
|
correlationId,
|
|
575
594
|
dataWithSuccessKeys: Object.keys(dataWithSuccess),
|
|
576
|
-
hasSuccess:
|
|
595
|
+
hasSuccess: "success" in dataWithSuccess,
|
|
577
596
|
successValue: dataWithSuccess.success,
|
|
578
|
-
hasAccepted:
|
|
597
|
+
hasAccepted: "accepted" in dataWithSuccess,
|
|
579
598
|
acceptedValue: dataWithSuccess.accepted,
|
|
580
|
-
hasRejected:
|
|
599
|
+
hasRejected: "rejected" in dataWithSuccess,
|
|
581
600
|
rejectedValue: dataWithSuccess.rejected,
|
|
582
|
-
hasOutcomes:
|
|
601
|
+
hasOutcomes: "outcomes" in dataWithSuccess,
|
|
583
602
|
outcomesValue: dataWithSuccess.outcomes,
|
|
584
603
|
fullDataWithSuccess: JSON.stringify(dataWithSuccess, null, 2),
|
|
585
604
|
});
|
|
586
605
|
|
|
587
606
|
// CRITICAL: Ensure all required fields are present before validation
|
|
588
|
-
if (
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
607
|
+
if (
|
|
608
|
+
typeof dataWithSuccess.accepted !== "number" ||
|
|
609
|
+
typeof dataWithSuccess.rejected !== "number"
|
|
610
|
+
) {
|
|
611
|
+
console.error(
|
|
612
|
+
`[AccessControl] ❌ MISSING REQUIRED FIELDS AFTER CONSTRUCTION:`,
|
|
613
|
+
{
|
|
614
|
+
correlationId,
|
|
615
|
+
hasAccepted: "accepted" in dataWithSuccess,
|
|
616
|
+
acceptedType: typeof dataWithSuccess.accepted,
|
|
617
|
+
acceptedValue: dataWithSuccess.accepted,
|
|
618
|
+
hasRejected: "rejected" in dataWithSuccess,
|
|
619
|
+
rejectedType: typeof dataWithSuccess.rejected,
|
|
620
|
+
rejectedValue: dataWithSuccess.rejected,
|
|
621
|
+
dataWithSuccessKeys: Object.keys(dataWithSuccess),
|
|
622
|
+
fullDataWithSuccess: JSON.stringify(dataWithSuccess, null, 2),
|
|
623
|
+
dataToValidateKeys: Object.keys(dataToValidate),
|
|
624
|
+
fullDataToValidate: JSON.stringify(dataToValidate, null, 2),
|
|
625
|
+
originalResponseData: JSON.stringify(responseData, null, 2),
|
|
626
|
+
}
|
|
627
|
+
);
|
|
603
628
|
throw new AgentShieldAPIError(
|
|
604
629
|
"invalid_response",
|
|
605
630
|
"Response data missing required fields (accepted/rejected)",
|
|
606
|
-
{
|
|
631
|
+
{
|
|
607
632
|
responseData,
|
|
608
633
|
dataToValidate,
|
|
609
634
|
dataWithSuccess,
|
|
@@ -657,22 +682,25 @@ export class AccessControlApiService {
|
|
|
657
682
|
`[AccessControl] Original wrapped response:`,
|
|
658
683
|
JSON.stringify(responseData, null, 2)
|
|
659
684
|
);
|
|
660
|
-
|
|
685
|
+
|
|
661
686
|
// CRITICAL: Log each zod error individually for easier debugging
|
|
662
687
|
console.error(
|
|
663
688
|
`[AccessControl] ❌ ZOD VALIDATION FAILED - ${dataParsed.error.errors.length} error(s):`
|
|
664
689
|
);
|
|
665
690
|
dataParsed.error.errors.forEach((err, idx) => {
|
|
666
691
|
const errorDetails: Record<string, unknown> = {
|
|
667
|
-
path: err.path.join(
|
|
692
|
+
path: err.path.join(".") || "(root)",
|
|
668
693
|
message: err.message,
|
|
669
694
|
code: err.code,
|
|
670
695
|
};
|
|
671
696
|
// Only include properties that exist on specific error types
|
|
672
|
-
if (
|
|
673
|
-
if (
|
|
674
|
-
if (
|
|
675
|
-
console.error(
|
|
697
|
+
if ("received" in err) errorDetails.received = err.received;
|
|
698
|
+
if ("expected" in err) errorDetails.expected = err.expected;
|
|
699
|
+
if ("input" in err) errorDetails.input = err.input;
|
|
700
|
+
console.error(
|
|
701
|
+
`[AccessControl] Error ${idx + 1}:`,
|
|
702
|
+
JSON.stringify(errorDetails, null, 2)
|
|
703
|
+
);
|
|
676
704
|
});
|
|
677
705
|
console.error(
|
|
678
706
|
`[AccessControl] ❌ Full ZOD errors JSON:`,
|
|
@@ -711,33 +739,30 @@ export class AccessControlApiService {
|
|
|
711
739
|
// CRITICAL: Log to console.error with full details for debugging
|
|
712
740
|
// This format matches test expectations: single call with message and error object
|
|
713
741
|
// This log must include 'Response validation failed' in the message for test compatibility
|
|
714
|
-
console.error(
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
responseData: responseData,
|
|
719
|
-
}
|
|
720
|
-
);
|
|
742
|
+
console.error(`[AccessControl] Response validation failed`, {
|
|
743
|
+
zodErrors: parsed.error.errors,
|
|
744
|
+
responseData: responseData,
|
|
745
|
+
});
|
|
721
746
|
// Additional detailed logging for debugging
|
|
722
747
|
console.error(
|
|
723
748
|
`[AccessControl] Response validation failed`,
|
|
724
749
|
validationErrorLog
|
|
725
750
|
);
|
|
726
|
-
|
|
751
|
+
|
|
727
752
|
// CRITICAL: Log each zod error individually for easier debugging
|
|
728
753
|
console.error(
|
|
729
754
|
`[AccessControl] ❌ ZOD VALIDATION FAILED (direct) - ${parsed.error.errors.length} error(s):`
|
|
730
755
|
);
|
|
731
756
|
parsed.error.errors.forEach((err, idx) => {
|
|
732
757
|
const errorDetails: Record<string, unknown> = {
|
|
733
|
-
path: err.path.join(
|
|
758
|
+
path: err.path.join(".") || "(root)",
|
|
734
759
|
message: err.message,
|
|
735
760
|
code: err.code,
|
|
736
761
|
};
|
|
737
762
|
// Only include properties that exist on specific error types
|
|
738
|
-
if (
|
|
739
|
-
if (
|
|
740
|
-
if (
|
|
763
|
+
if ("received" in err) errorDetails.received = err.received;
|
|
764
|
+
if ("expected" in err) errorDetails.expected = err.expected;
|
|
765
|
+
if ("input" in err) errorDetails.input = err.input;
|
|
741
766
|
console.error(`[AccessControl] Error ${idx + 1}:`, errorDetails);
|
|
742
767
|
});
|
|
743
768
|
console.error(
|