cuonztech-privacy-chaos-gate 0.2.0 → 0.2.2
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/LICENSE +97 -0
- package/README.md +197 -30
- package/action.yml +187 -26
- package/dist/chunk-42D7PLVP.js +9146 -0
- package/dist/cli.js +96 -93
- package/dist/index.d.ts +710 -88
- package/dist/index.js +41 -12
- package/docs/BRAND-PILOT-EVIDENCE.md +41 -49
- package/package.json +6 -5
- package/dist/chunk-FN3QUFUZ.js +0 -36
- package/dist/chunk-FN3QUFUZ.js.map +0 -1
- package/dist/chunk-T5D6BUAC.js +0 -4514
- package/dist/chunk-T5D6BUAC.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/resolveGrant-6U6VG3DM.js +0 -230
- package/dist/resolveGrant-6U6VG3DM.js.map +0 -1
- package/docs/LIZENZ-KAUFFLUSS.md +0 -105
- package/docs/PREISMODELL.md +0 -63
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import * as playwright from 'playwright';
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* Chaos test scenarios as defined in PRD Section 2B
|
|
@@ -207,17 +206,19 @@ declare const EvidenceRecordSchema: z.ZodObject<{
|
|
|
207
206
|
path: z.ZodString;
|
|
208
207
|
at: z.ZodString;
|
|
209
208
|
}, "strip", z.ZodTypeAny, {
|
|
210
|
-
at: string;
|
|
211
209
|
path: string;
|
|
210
|
+
at: string;
|
|
212
211
|
label: string;
|
|
213
212
|
}, {
|
|
214
|
-
at: string;
|
|
215
213
|
path: string;
|
|
214
|
+
at: string;
|
|
216
215
|
label: string;
|
|
217
216
|
}>, "many">>;
|
|
218
217
|
screenshotPath: z.ZodOptional<z.ZodString>;
|
|
219
218
|
targetUrl: z.ZodString;
|
|
220
219
|
checkedAt: z.ZodString;
|
|
220
|
+
/** Nur nach `--ignore`: so viele Befunde dieses Szenarios wurden ausgenommen (bei Status «bestanden» alle). */
|
|
221
|
+
ignoredFindings: z.ZodOptional<z.ZodNumber>;
|
|
221
222
|
}, "strip", z.ZodTypeAny, {
|
|
222
223
|
targetUrl: string;
|
|
223
224
|
status: "passed" | "suspicious" | "not-checkable" | "not-applicable";
|
|
@@ -265,11 +266,12 @@ declare const EvidenceRecordSchema: z.ZodObject<{
|
|
|
265
266
|
} | undefined;
|
|
266
267
|
residualAfterRevoke?: string[] | undefined;
|
|
267
268
|
screenshots?: {
|
|
268
|
-
at: string;
|
|
269
269
|
path: string;
|
|
270
|
+
at: string;
|
|
270
271
|
label: string;
|
|
271
272
|
}[] | undefined;
|
|
272
273
|
screenshotPath?: string | undefined;
|
|
274
|
+
ignoredFindings?: number | undefined;
|
|
273
275
|
}, {
|
|
274
276
|
targetUrl: string;
|
|
275
277
|
status: "passed" | "suspicious" | "not-checkable" | "not-applicable";
|
|
@@ -317,11 +319,12 @@ declare const EvidenceRecordSchema: z.ZodObject<{
|
|
|
317
319
|
} | undefined;
|
|
318
320
|
residualAfterRevoke?: string[] | undefined;
|
|
319
321
|
screenshots?: {
|
|
320
|
-
at: string;
|
|
321
322
|
path: string;
|
|
323
|
+
at: string;
|
|
322
324
|
label: string;
|
|
323
325
|
}[] | undefined;
|
|
324
326
|
screenshotPath?: string | undefined;
|
|
327
|
+
ignoredFindings?: number | undefined;
|
|
325
328
|
}>;
|
|
326
329
|
type EvidenceRecord = z.infer<typeof EvidenceRecordSchema>;
|
|
327
330
|
/**
|
|
@@ -338,8 +341,13 @@ declare const TrackerViolationSchema: z.ZodObject<{
|
|
|
338
341
|
trackerName: z.ZodString;
|
|
339
342
|
trackerCategory: z.ZodEnum<["analytics", "marketing", "functional", "unknown"]>;
|
|
340
343
|
requestUrl: z.ZodString;
|
|
341
|
-
/**
|
|
344
|
+
/**
|
|
345
|
+
* Verletzte Regel — steuert Gate-Wortlaut und Empfehlungen
|
|
346
|
+
* (u. a. "pre-consent-tracking", "tracking-after-deny", "no-reject-option").
|
|
347
|
+
*/
|
|
342
348
|
ruleId: z.ZodOptional<z.ZodString>;
|
|
349
|
+
/** Hinweis ohne Gate-Wirkung (z. B. rein funktionale Drittanbieter wie Google Fonts) */
|
|
350
|
+
advisory: z.ZodOptional<z.ZodBoolean>;
|
|
343
351
|
method: z.ZodDefault<z.ZodString>;
|
|
344
352
|
timestamp: z.ZodString;
|
|
345
353
|
domContext: z.ZodOptional<z.ZodObject<{
|
|
@@ -366,6 +374,7 @@ declare const TrackerViolationSchema: z.ZodObject<{
|
|
|
366
374
|
timestamp: string;
|
|
367
375
|
description: string;
|
|
368
376
|
ruleId?: string | undefined;
|
|
377
|
+
advisory?: boolean | undefined;
|
|
369
378
|
domContext?: {
|
|
370
379
|
triggerElement?: string | undefined;
|
|
371
380
|
consentBannerVisible?: boolean | undefined;
|
|
@@ -380,6 +389,7 @@ declare const TrackerViolationSchema: z.ZodObject<{
|
|
|
380
389
|
timestamp: string;
|
|
381
390
|
description: string;
|
|
382
391
|
ruleId?: string | undefined;
|
|
392
|
+
advisory?: boolean | undefined;
|
|
383
393
|
method?: string | undefined;
|
|
384
394
|
domContext?: {
|
|
385
395
|
triggerElement?: string | undefined;
|
|
@@ -402,8 +412,13 @@ declare const LeakReportSchema: z.ZodObject<{
|
|
|
402
412
|
trackerName: z.ZodString;
|
|
403
413
|
trackerCategory: z.ZodEnum<["analytics", "marketing", "functional", "unknown"]>;
|
|
404
414
|
requestUrl: z.ZodString;
|
|
405
|
-
/**
|
|
415
|
+
/**
|
|
416
|
+
* Verletzte Regel — steuert Gate-Wortlaut und Empfehlungen
|
|
417
|
+
* (u. a. "pre-consent-tracking", "tracking-after-deny", "no-reject-option").
|
|
418
|
+
*/
|
|
406
419
|
ruleId: z.ZodOptional<z.ZodString>;
|
|
420
|
+
/** Hinweis ohne Gate-Wirkung (z. B. rein funktionale Drittanbieter wie Google Fonts) */
|
|
421
|
+
advisory: z.ZodOptional<z.ZodBoolean>;
|
|
407
422
|
method: z.ZodDefault<z.ZodString>;
|
|
408
423
|
timestamp: z.ZodString;
|
|
409
424
|
domContext: z.ZodOptional<z.ZodObject<{
|
|
@@ -430,6 +445,7 @@ declare const LeakReportSchema: z.ZodObject<{
|
|
|
430
445
|
timestamp: string;
|
|
431
446
|
description: string;
|
|
432
447
|
ruleId?: string | undefined;
|
|
448
|
+
advisory?: boolean | undefined;
|
|
433
449
|
domContext?: {
|
|
434
450
|
triggerElement?: string | undefined;
|
|
435
451
|
consentBannerVisible?: boolean | undefined;
|
|
@@ -444,6 +460,7 @@ declare const LeakReportSchema: z.ZodObject<{
|
|
|
444
460
|
timestamp: string;
|
|
445
461
|
description: string;
|
|
446
462
|
ruleId?: string | undefined;
|
|
463
|
+
advisory?: boolean | undefined;
|
|
447
464
|
method?: string | undefined;
|
|
448
465
|
domContext?: {
|
|
449
466
|
triggerElement?: string | undefined;
|
|
@@ -593,17 +610,19 @@ declare const LeakReportSchema: z.ZodObject<{
|
|
|
593
610
|
path: z.ZodString;
|
|
594
611
|
at: z.ZodString;
|
|
595
612
|
}, "strip", z.ZodTypeAny, {
|
|
596
|
-
at: string;
|
|
597
613
|
path: string;
|
|
614
|
+
at: string;
|
|
598
615
|
label: string;
|
|
599
616
|
}, {
|
|
600
|
-
at: string;
|
|
601
617
|
path: string;
|
|
618
|
+
at: string;
|
|
602
619
|
label: string;
|
|
603
620
|
}>, "many">>;
|
|
604
621
|
screenshotPath: z.ZodOptional<z.ZodString>;
|
|
605
622
|
targetUrl: z.ZodString;
|
|
606
623
|
checkedAt: z.ZodString;
|
|
624
|
+
/** Nur nach `--ignore`: so viele Befunde dieses Szenarios wurden ausgenommen (bei Status «bestanden» alle). */
|
|
625
|
+
ignoredFindings: z.ZodOptional<z.ZodNumber>;
|
|
607
626
|
}, "strip", z.ZodTypeAny, {
|
|
608
627
|
targetUrl: string;
|
|
609
628
|
status: "passed" | "suspicious" | "not-checkable" | "not-applicable";
|
|
@@ -651,11 +670,12 @@ declare const LeakReportSchema: z.ZodObject<{
|
|
|
651
670
|
} | undefined;
|
|
652
671
|
residualAfterRevoke?: string[] | undefined;
|
|
653
672
|
screenshots?: {
|
|
654
|
-
at: string;
|
|
655
673
|
path: string;
|
|
674
|
+
at: string;
|
|
656
675
|
label: string;
|
|
657
676
|
}[] | undefined;
|
|
658
677
|
screenshotPath?: string | undefined;
|
|
678
|
+
ignoredFindings?: number | undefined;
|
|
659
679
|
}, {
|
|
660
680
|
targetUrl: string;
|
|
661
681
|
status: "passed" | "suspicious" | "not-checkable" | "not-applicable";
|
|
@@ -703,12 +723,59 @@ declare const LeakReportSchema: z.ZodObject<{
|
|
|
703
723
|
} | undefined;
|
|
704
724
|
residualAfterRevoke?: string[] | undefined;
|
|
705
725
|
screenshots?: {
|
|
706
|
-
at: string;
|
|
707
726
|
path: string;
|
|
727
|
+
at: string;
|
|
708
728
|
label: string;
|
|
709
729
|
}[] | undefined;
|
|
710
730
|
screenshotPath?: string | undefined;
|
|
731
|
+
ignoredFindings?: number | undefined;
|
|
711
732
|
}>, "many">>;
|
|
733
|
+
/** Per `--ignore` gefilterte Befunde — werden ausgewiesen, nicht verschwiegen. */
|
|
734
|
+
ignored: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
735
|
+
trackerName: z.ZodString;
|
|
736
|
+
requestUrl: z.ZodString;
|
|
737
|
+
scenario: z.ZodEnum<["happy-path-denied", "happy-path-accepted", "fast-click", "state-manipulation", "network-drop", "consent-revoked", "category-selective", "consent-persistence", "banner-ignored", "subpage-spa", "cmp-failure", "embed-leaks", "consent-mode-v2", "duplicate-events", "mobile-usability"]>;
|
|
738
|
+
pattern: z.ZodString;
|
|
739
|
+
}, "strip", z.ZodTypeAny, {
|
|
740
|
+
trackerName: string;
|
|
741
|
+
scenario: "happy-path-denied" | "happy-path-accepted" | "fast-click" | "state-manipulation" | "network-drop" | "consent-revoked" | "category-selective" | "consent-persistence" | "banner-ignored" | "subpage-spa" | "cmp-failure" | "embed-leaks" | "consent-mode-v2" | "duplicate-events" | "mobile-usability";
|
|
742
|
+
requestUrl: string;
|
|
743
|
+
pattern: string;
|
|
744
|
+
}, {
|
|
745
|
+
trackerName: string;
|
|
746
|
+
scenario: "happy-path-denied" | "happy-path-accepted" | "fast-click" | "state-manipulation" | "network-drop" | "consent-revoked" | "category-selective" | "consent-persistence" | "banner-ignored" | "subpage-spa" | "cmp-failure" | "embed-leaks" | "consent-mode-v2" | "duplicate-events" | "mobile-usability";
|
|
747
|
+
requestUrl: string;
|
|
748
|
+
pattern: string;
|
|
749
|
+
}>, "many">>;
|
|
750
|
+
/**
|
|
751
|
+
* Scanner: wurde irgendwo ein Consent-Banner-Element sichtbar gesehen (auch wenn Accept/Reject nicht klickbar
|
|
752
|
+
* erkannt wurden)? `false` = Suche endete vollständig ohne Banner-Hinweis; `undefined` = nicht ermittelt.
|
|
753
|
+
*/
|
|
754
|
+
bannerObserved: z.ZodOptional<z.ZodBoolean>;
|
|
755
|
+
/** Scanner: Hinweise zur Reichweite des Scans (ungültige/ungenutzte Override-Selektoren, spät erschienener Banner). */
|
|
756
|
+
scannerWarnings: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
757
|
+
/**
|
|
758
|
+
* Szenario `subpage-spa`: so viele der verlinkten Unterseiten wurden geprüft (`checked`, HTTP < 400) von allen
|
|
759
|
+
* verlinkten (`linked`); `max` ist die Obergrenze der Stichprobe (`--max-subpages`). Fehlt, wenn das Szenario nicht lief.
|
|
760
|
+
*/
|
|
761
|
+
subpageSampling: z.ZodOptional<z.ZodObject<{
|
|
762
|
+
checked: z.ZodNumber;
|
|
763
|
+
linked: z.ZodNumber;
|
|
764
|
+
max: z.ZodNumber;
|
|
765
|
+
}, "strip", z.ZodTypeAny, {
|
|
766
|
+
checked: number;
|
|
767
|
+
linked: number;
|
|
768
|
+
max: number;
|
|
769
|
+
}, {
|
|
770
|
+
checked: number;
|
|
771
|
+
linked: number;
|
|
772
|
+
max: number;
|
|
773
|
+
}>>;
|
|
774
|
+
/**
|
|
775
|
+
* Warum «kein Banner» nicht belegt ist: `unstable` (Reload-Schleife, Banner nicht auswertbar), `late` (Banner erschien
|
|
776
|
+
* nach dem Wartefenster), `inoperable` (Banner vorhanden, aber nicht über Ablehnen/Akzeptieren bedienbar).
|
|
777
|
+
*/
|
|
778
|
+
bannerIssue: z.ZodOptional<z.ZodEnum<["unstable", "late", "inoperable"]>>;
|
|
712
779
|
}, "strip", z.ZodTypeAny, {
|
|
713
780
|
targetUrl: string;
|
|
714
781
|
scannedAt: string;
|
|
@@ -724,6 +791,7 @@ declare const LeakReportSchema: z.ZodObject<{
|
|
|
724
791
|
timestamp: string;
|
|
725
792
|
description: string;
|
|
726
793
|
ruleId?: string | undefined;
|
|
794
|
+
advisory?: boolean | undefined;
|
|
727
795
|
domContext?: {
|
|
728
796
|
triggerElement?: string | undefined;
|
|
729
797
|
consentBannerVisible?: boolean | undefined;
|
|
@@ -780,12 +848,27 @@ declare const LeakReportSchema: z.ZodObject<{
|
|
|
780
848
|
} | undefined;
|
|
781
849
|
residualAfterRevoke?: string[] | undefined;
|
|
782
850
|
screenshots?: {
|
|
783
|
-
at: string;
|
|
784
851
|
path: string;
|
|
852
|
+
at: string;
|
|
785
853
|
label: string;
|
|
786
854
|
}[] | undefined;
|
|
787
855
|
screenshotPath?: string | undefined;
|
|
856
|
+
ignoredFindings?: number | undefined;
|
|
857
|
+
}[] | undefined;
|
|
858
|
+
ignored?: {
|
|
859
|
+
trackerName: string;
|
|
860
|
+
scenario: "happy-path-denied" | "happy-path-accepted" | "fast-click" | "state-manipulation" | "network-drop" | "consent-revoked" | "category-selective" | "consent-persistence" | "banner-ignored" | "subpage-spa" | "cmp-failure" | "embed-leaks" | "consent-mode-v2" | "duplicate-events" | "mobile-usability";
|
|
861
|
+
requestUrl: string;
|
|
862
|
+
pattern: string;
|
|
788
863
|
}[] | undefined;
|
|
864
|
+
bannerObserved?: boolean | undefined;
|
|
865
|
+
scannerWarnings?: string[] | undefined;
|
|
866
|
+
subpageSampling?: {
|
|
867
|
+
checked: number;
|
|
868
|
+
linked: number;
|
|
869
|
+
max: number;
|
|
870
|
+
} | undefined;
|
|
871
|
+
bannerIssue?: "unstable" | "late" | "inoperable" | undefined;
|
|
789
872
|
}, {
|
|
790
873
|
targetUrl: string;
|
|
791
874
|
scannedAt: string;
|
|
@@ -800,6 +883,7 @@ declare const LeakReportSchema: z.ZodObject<{
|
|
|
800
883
|
timestamp: string;
|
|
801
884
|
description: string;
|
|
802
885
|
ruleId?: string | undefined;
|
|
886
|
+
advisory?: boolean | undefined;
|
|
803
887
|
method?: string | undefined;
|
|
804
888
|
domContext?: {
|
|
805
889
|
triggerElement?: string | undefined;
|
|
@@ -857,14 +941,31 @@ declare const LeakReportSchema: z.ZodObject<{
|
|
|
857
941
|
} | undefined;
|
|
858
942
|
residualAfterRevoke?: string[] | undefined;
|
|
859
943
|
screenshots?: {
|
|
860
|
-
at: string;
|
|
861
944
|
path: string;
|
|
945
|
+
at: string;
|
|
862
946
|
label: string;
|
|
863
947
|
}[] | undefined;
|
|
864
948
|
screenshotPath?: string | undefined;
|
|
949
|
+
ignoredFindings?: number | undefined;
|
|
865
950
|
}[] | undefined;
|
|
951
|
+
ignored?: {
|
|
952
|
+
trackerName: string;
|
|
953
|
+
scenario: "happy-path-denied" | "happy-path-accepted" | "fast-click" | "state-manipulation" | "network-drop" | "consent-revoked" | "category-selective" | "consent-persistence" | "banner-ignored" | "subpage-spa" | "cmp-failure" | "embed-leaks" | "consent-mode-v2" | "duplicate-events" | "mobile-usability";
|
|
954
|
+
requestUrl: string;
|
|
955
|
+
pattern: string;
|
|
956
|
+
}[] | undefined;
|
|
957
|
+
bannerObserved?: boolean | undefined;
|
|
958
|
+
scannerWarnings?: string[] | undefined;
|
|
959
|
+
subpageSampling?: {
|
|
960
|
+
checked: number;
|
|
961
|
+
linked: number;
|
|
962
|
+
max: number;
|
|
963
|
+
} | undefined;
|
|
964
|
+
bannerIssue?: "unstable" | "late" | "inoperable" | undefined;
|
|
866
965
|
}>;
|
|
966
|
+
type BannerIssue = NonNullable<z.infer<typeof LeakReportSchema>["bannerIssue"]>;
|
|
867
967
|
type LeakReport = z.infer<typeof LeakReportSchema>;
|
|
968
|
+
type IgnoredFinding = NonNullable<LeakReport["ignored"]>[number];
|
|
868
969
|
/**
|
|
869
970
|
* Patch proposal produced by the remediation engine
|
|
870
971
|
*/
|
|
@@ -933,6 +1034,17 @@ declare const ReviewVerdictSchema: z.ZodObject<{
|
|
|
933
1034
|
originalContent?: string | undefined;
|
|
934
1035
|
diff?: string | undefined;
|
|
935
1036
|
}>, "many">;
|
|
1037
|
+
/** Teilfix: Score und `passed` gelten nur für den gepatchten Teil (`covered` von `total` gemeldeten Trackern). */
|
|
1038
|
+
partial: z.ZodOptional<z.ZodObject<{
|
|
1039
|
+
covered: z.ZodNumber;
|
|
1040
|
+
total: z.ZodNumber;
|
|
1041
|
+
}, "strip", z.ZodTypeAny, {
|
|
1042
|
+
covered: number;
|
|
1043
|
+
total: number;
|
|
1044
|
+
}, {
|
|
1045
|
+
covered: number;
|
|
1046
|
+
total: number;
|
|
1047
|
+
}>>;
|
|
936
1048
|
}, "strip", z.ZodTypeAny, {
|
|
937
1049
|
passed: boolean;
|
|
938
1050
|
score: number;
|
|
@@ -951,6 +1063,10 @@ declare const ReviewVerdictSchema: z.ZodObject<{
|
|
|
951
1063
|
originalContent?: string | undefined;
|
|
952
1064
|
diff?: string | undefined;
|
|
953
1065
|
}[];
|
|
1066
|
+
partial?: {
|
|
1067
|
+
covered: number;
|
|
1068
|
+
total: number;
|
|
1069
|
+
} | undefined;
|
|
954
1070
|
}, {
|
|
955
1071
|
passed: boolean;
|
|
956
1072
|
score: number;
|
|
@@ -969,6 +1085,10 @@ declare const ReviewVerdictSchema: z.ZodObject<{
|
|
|
969
1085
|
originalContent?: string | undefined;
|
|
970
1086
|
diff?: string | undefined;
|
|
971
1087
|
}[];
|
|
1088
|
+
partial?: {
|
|
1089
|
+
covered: number;
|
|
1090
|
+
total: number;
|
|
1091
|
+
} | undefined;
|
|
972
1092
|
}>;
|
|
973
1093
|
type ReviewVerdict = z.infer<typeof ReviewVerdictSchema>;
|
|
974
1094
|
/**
|
|
@@ -1060,6 +1180,17 @@ declare const RemediationResultSchema: z.ZodObject<{
|
|
|
1060
1180
|
originalContent?: string | undefined;
|
|
1061
1181
|
diff?: string | undefined;
|
|
1062
1182
|
}>, "many">;
|
|
1183
|
+
/** Teilfix: Score und `passed` gelten nur für den gepatchten Teil (`covered` von `total` gemeldeten Trackern). */
|
|
1184
|
+
partial: z.ZodOptional<z.ZodObject<{
|
|
1185
|
+
covered: z.ZodNumber;
|
|
1186
|
+
total: z.ZodNumber;
|
|
1187
|
+
}, "strip", z.ZodTypeAny, {
|
|
1188
|
+
covered: number;
|
|
1189
|
+
total: number;
|
|
1190
|
+
}, {
|
|
1191
|
+
covered: number;
|
|
1192
|
+
total: number;
|
|
1193
|
+
}>>;
|
|
1063
1194
|
}, "strip", z.ZodTypeAny, {
|
|
1064
1195
|
passed: boolean;
|
|
1065
1196
|
score: number;
|
|
@@ -1078,6 +1209,10 @@ declare const RemediationResultSchema: z.ZodObject<{
|
|
|
1078
1209
|
originalContent?: string | undefined;
|
|
1079
1210
|
diff?: string | undefined;
|
|
1080
1211
|
}[];
|
|
1212
|
+
partial?: {
|
|
1213
|
+
covered: number;
|
|
1214
|
+
total: number;
|
|
1215
|
+
} | undefined;
|
|
1081
1216
|
}, {
|
|
1082
1217
|
passed: boolean;
|
|
1083
1218
|
score: number;
|
|
@@ -1096,6 +1231,10 @@ declare const RemediationResultSchema: z.ZodObject<{
|
|
|
1096
1231
|
originalContent?: string | undefined;
|
|
1097
1232
|
diff?: string | undefined;
|
|
1098
1233
|
}[];
|
|
1234
|
+
partial?: {
|
|
1235
|
+
covered: number;
|
|
1236
|
+
total: number;
|
|
1237
|
+
} | undefined;
|
|
1099
1238
|
}>>;
|
|
1100
1239
|
commitHash: z.ZodOptional<z.ZodString>;
|
|
1101
1240
|
commitMessage: z.ZodOptional<z.ZodString>;
|
|
@@ -1149,6 +1288,10 @@ declare const RemediationResultSchema: z.ZodObject<{
|
|
|
1149
1288
|
originalContent?: string | undefined;
|
|
1150
1289
|
diff?: string | undefined;
|
|
1151
1290
|
}[];
|
|
1291
|
+
partial?: {
|
|
1292
|
+
covered: number;
|
|
1293
|
+
total: number;
|
|
1294
|
+
} | undefined;
|
|
1152
1295
|
} | undefined;
|
|
1153
1296
|
commitHash?: string | undefined;
|
|
1154
1297
|
commitMessage?: string | undefined;
|
|
@@ -1188,6 +1331,10 @@ declare const RemediationResultSchema: z.ZodObject<{
|
|
|
1188
1331
|
originalContent?: string | undefined;
|
|
1189
1332
|
diff?: string | undefined;
|
|
1190
1333
|
}[];
|
|
1334
|
+
partial?: {
|
|
1335
|
+
covered: number;
|
|
1336
|
+
total: number;
|
|
1337
|
+
} | undefined;
|
|
1191
1338
|
} | undefined;
|
|
1192
1339
|
commitHash?: string | undefined;
|
|
1193
1340
|
commitMessage?: string | undefined;
|
|
@@ -1202,16 +1349,26 @@ declare const RemediationResultSchema: z.ZodObject<{
|
|
|
1202
1349
|
error?: string | undefined;
|
|
1203
1350
|
}>;
|
|
1204
1351
|
type RemediationResult = z.infer<typeof RemediationResultSchema>;
|
|
1352
|
+
/**
|
|
1353
|
+
* Rechtsräume, die `--jurisdiction` akzeptiert (siehe core/legal/jurisdictions.ts).
|
|
1354
|
+
*/
|
|
1355
|
+
declare const JurisdictionCodeSchema: z.ZodEnum<["CH", "EU", "UK", "US-CA", "BR", "ROW"]>;
|
|
1205
1356
|
/**
|
|
1206
1357
|
* Privacy Gate CLI & Configuration Options
|
|
1207
1358
|
*/
|
|
1208
1359
|
declare const GateConfigSchema: z.ZodObject<{
|
|
1209
|
-
targetUrl: z.ZodString
|
|
1360
|
+
targetUrl: z.ZodEffects<z.ZodString, string, string>;
|
|
1361
|
+
/** LLM-Key — wird nur gesetzt, wenn `llmRemediation` aktiv ist (siehe resolveGateConfig). */
|
|
1210
1362
|
apiKey: z.ZodOptional<z.ZodString>;
|
|
1211
1363
|
llmProvider: z.ZodDefault<z.ZodEnum<["openai", "anthropic", "gemini"]>>;
|
|
1212
1364
|
llmModel: z.ZodDefault<z.ZodString>;
|
|
1365
|
+
/** Explizites Opt-in: Quellcode darf zur Patch-Erzeugung an den LLM-Anbieter gesendet werden. */
|
|
1366
|
+
llmRemediation: z.ZodDefault<z.ZodBoolean>;
|
|
1367
|
+
/** Default aus: Auto-Fix schreibt nur, wenn der Aufrufer ihn ausdrücklich anfordert. */
|
|
1213
1368
|
autoFix: z.ZodDefault<z.ZodBoolean>;
|
|
1214
1369
|
failOnLeak: z.ZodDefault<z.ZodBoolean>;
|
|
1370
|
+
/** Kernszenarien nicht prüfbar ⇒ Exit 4 (INCONCLUSIVE) statt stiller Freigabe. */
|
|
1371
|
+
failOnUncheckable: z.ZodDefault<z.ZodBoolean>;
|
|
1215
1372
|
reportOutput: z.ZodDefault<z.ZodString>;
|
|
1216
1373
|
sourceDir: z.ZodDefault<z.ZodString>;
|
|
1217
1374
|
gitCommit: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -1221,27 +1378,73 @@ declare const GateConfigSchema: z.ZodObject<{
|
|
|
1221
1378
|
branchPrefix: z.ZodDefault<z.ZodString>;
|
|
1222
1379
|
/** Optional: nur diese Szenarien ausführen (leer = alle). Für Tests/CI gezielt. */
|
|
1223
1380
|
scenarios: z.ZodOptional<z.ZodArray<z.ZodEnum<["happy-path-denied", "happy-path-accepted", "fast-click", "state-manipulation", "network-drop", "consent-revoked", "category-selective", "consent-persistence", "banner-ignored", "subpage-spa", "cmp-failure", "embed-leaks", "consent-mode-v2", "duplicate-events", "mobile-usability"]>, "many">>;
|
|
1381
|
+
/** Rechtsraum, der in Konsole und report.json hervorgehoben wird (der Report führt alle Räume auf). */
|
|
1382
|
+
jurisdiction: z.ZodDefault<z.ZodEnum<["CH", "EU", "UK", "US-CA", "BR", "ROW"]>>;
|
|
1224
1383
|
/** Demo-Lauf mit synthetischen Testdaten — Report wird gekennzeichnet */
|
|
1225
1384
|
demo: z.ZodOptional<z.ZodBoolean>;
|
|
1226
1385
|
/** Deluxe-PDF (Deckblatt + Evidence) nach dem Scan erzeugen */
|
|
1227
1386
|
reportPdf: z.ZodOptional<z.ZodBoolean>;
|
|
1228
|
-
/** Kundenname für das PDF-Deckblatt */
|
|
1387
|
+
/** Kundenname für das PDF-Deckblatt (Default: Host der Ziel-URL) */
|
|
1229
1388
|
clientName: z.ZodOptional<z.ZodString>;
|
|
1230
1389
|
headless: z.ZodDefault<z.ZodBoolean>;
|
|
1390
|
+
/** Timeout je Szenario-Navigation und für den Erreichbarkeits-Check (ms) */
|
|
1231
1391
|
timeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
1392
|
+
/** Hinweise (advisory, z. B. rein funktionale Google Fonts) blockieren das Gate ebenfalls. */
|
|
1393
|
+
strict: z.ZodDefault<z.ZodBoolean>;
|
|
1394
|
+
/** Tracker-Namen oder Host-Muster (`fonts.googleapis.com`, `*.hotjar.com`), die als «ignoriert» ausgewiesen werden. */
|
|
1395
|
+
ignore: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
1396
|
+
/** Erlaubt sehr breite `--ignore`-Muster (`*`, `*.com`, einzelne TLD); sonst Exit 3. Nur CLI/echte Umgebung. */
|
|
1397
|
+
allowBroadIgnore: z.ZodDefault<z.ZodBoolean>;
|
|
1398
|
+
/** Obergrenze der Unterseiten-Stichprobe (Szenario subpage-spa), `--max-subpages` (Standard 12, höchstens 40). */
|
|
1399
|
+
maxSubpages: z.ZodDefault<z.ZodNumber>;
|
|
1400
|
+
/**
|
|
1401
|
+
* Wartefenster auf einen (spät erscheinenden) Banner in Sekunden, `--banner-wait` (höchstens 60). Ohne Angabe gilt das
|
|
1402
|
+
* bisherige Verhalten (8 s, bei Seiten ohne Banner-Hinweis früher beendet); mit Angabe wird das Fenster ausgeschöpft.
|
|
1403
|
+
*/
|
|
1404
|
+
bannerWaitSeconds: z.ZodOptional<z.ZodNumber>;
|
|
1405
|
+
/** Hinweise zur Eingabe (z. B. leerer Selektor), die der Scanner in `scannerWarnings` übernimmt. */
|
|
1406
|
+
configWarnings: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1407
|
+
/** Scanner-Overrides für eigene Banner (CSS-Selektoren bzw. Teilstring der Banner-Frame-URL). */
|
|
1408
|
+
acceptSelectors: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1409
|
+
rejectSelectors: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1410
|
+
settingsSelectors: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1411
|
+
bannerFrame: z.ZodOptional<z.ZodString>;
|
|
1412
|
+
/**
|
|
1413
|
+
* Lizenzstatus — wird ausschliesslich von der CLI (oder dem Aufrufer der API) gesetzt, nie aus Env/.env.
|
|
1414
|
+
* Ohne gültige Lizenz laufen PDF-Report, Kundenreport (`client`), `gitCommit` und `createPr` nicht
|
|
1415
|
+
* (Scan und Gate bleiben frei; Loopback-Ziele sind immer frei).
|
|
1416
|
+
*/
|
|
1417
|
+
license: z.ZodOptional<z.ZodObject<{
|
|
1418
|
+
entitled: z.ZodBoolean;
|
|
1419
|
+
/** Warum nicht lizenziert: keine Lizenz gesetzt | Lizenzserver nicht erreichbar */
|
|
1420
|
+
reason: z.ZodOptional<z.ZodEnum<["none", "unreachable"]>>;
|
|
1421
|
+
}, "strip", z.ZodTypeAny, {
|
|
1422
|
+
entitled: boolean;
|
|
1423
|
+
reason?: "none" | "unreachable" | undefined;
|
|
1424
|
+
}, {
|
|
1425
|
+
entitled: boolean;
|
|
1426
|
+
reason?: "none" | "unreachable" | undefined;
|
|
1427
|
+
}>>;
|
|
1232
1428
|
}, "strip", z.ZodTypeAny, {
|
|
1233
1429
|
targetUrl: string;
|
|
1234
1430
|
llmProvider: "openai" | "anthropic" | "gemini";
|
|
1235
1431
|
llmModel: string;
|
|
1432
|
+
llmRemediation: boolean;
|
|
1236
1433
|
autoFix: boolean;
|
|
1237
1434
|
failOnLeak: boolean;
|
|
1435
|
+
failOnUncheckable: boolean;
|
|
1238
1436
|
reportOutput: string;
|
|
1239
1437
|
sourceDir: string;
|
|
1240
1438
|
gitCommit: boolean;
|
|
1241
1439
|
createPr: boolean;
|
|
1242
1440
|
branchPrefix: string;
|
|
1441
|
+
jurisdiction: "CH" | "EU" | "UK" | "US-CA" | "BR" | "ROW";
|
|
1243
1442
|
headless: boolean;
|
|
1244
1443
|
timeoutMs: number;
|
|
1444
|
+
strict: boolean;
|
|
1445
|
+
ignore: string[];
|
|
1446
|
+
allowBroadIgnore: boolean;
|
|
1447
|
+
maxSubpages: number;
|
|
1245
1448
|
apiKey?: string | undefined;
|
|
1246
1449
|
githubToken?: string | undefined;
|
|
1247
1450
|
baseBranch?: string | undefined;
|
|
@@ -1249,13 +1452,25 @@ declare const GateConfigSchema: z.ZodObject<{
|
|
|
1249
1452
|
demo?: boolean | undefined;
|
|
1250
1453
|
reportPdf?: boolean | undefined;
|
|
1251
1454
|
clientName?: string | undefined;
|
|
1455
|
+
bannerWaitSeconds?: number | undefined;
|
|
1456
|
+
configWarnings?: string[] | undefined;
|
|
1457
|
+
acceptSelectors?: string[] | undefined;
|
|
1458
|
+
rejectSelectors?: string[] | undefined;
|
|
1459
|
+
settingsSelectors?: string[] | undefined;
|
|
1460
|
+
bannerFrame?: string | undefined;
|
|
1461
|
+
license?: {
|
|
1462
|
+
entitled: boolean;
|
|
1463
|
+
reason?: "none" | "unreachable" | undefined;
|
|
1464
|
+
} | undefined;
|
|
1252
1465
|
}, {
|
|
1253
1466
|
targetUrl: string;
|
|
1254
1467
|
apiKey?: string | undefined;
|
|
1255
1468
|
llmProvider?: "openai" | "anthropic" | "gemini" | undefined;
|
|
1256
1469
|
llmModel?: string | undefined;
|
|
1470
|
+
llmRemediation?: boolean | undefined;
|
|
1257
1471
|
autoFix?: boolean | undefined;
|
|
1258
1472
|
failOnLeak?: boolean | undefined;
|
|
1473
|
+
failOnUncheckable?: boolean | undefined;
|
|
1259
1474
|
reportOutput?: string | undefined;
|
|
1260
1475
|
sourceDir?: string | undefined;
|
|
1261
1476
|
gitCommit?: boolean | undefined;
|
|
@@ -1264,23 +1479,129 @@ declare const GateConfigSchema: z.ZodObject<{
|
|
|
1264
1479
|
baseBranch?: string | undefined;
|
|
1265
1480
|
branchPrefix?: string | undefined;
|
|
1266
1481
|
scenarios?: ("happy-path-denied" | "happy-path-accepted" | "fast-click" | "state-manipulation" | "network-drop" | "consent-revoked" | "category-selective" | "consent-persistence" | "banner-ignored" | "subpage-spa" | "cmp-failure" | "embed-leaks" | "consent-mode-v2" | "duplicate-events" | "mobile-usability")[] | undefined;
|
|
1482
|
+
jurisdiction?: "CH" | "EU" | "UK" | "US-CA" | "BR" | "ROW" | undefined;
|
|
1267
1483
|
demo?: boolean | undefined;
|
|
1268
1484
|
reportPdf?: boolean | undefined;
|
|
1269
1485
|
clientName?: string | undefined;
|
|
1270
1486
|
headless?: boolean | undefined;
|
|
1271
1487
|
timeoutMs?: number | undefined;
|
|
1488
|
+
strict?: boolean | undefined;
|
|
1489
|
+
ignore?: string[] | undefined;
|
|
1490
|
+
allowBroadIgnore?: boolean | undefined;
|
|
1491
|
+
maxSubpages?: number | undefined;
|
|
1492
|
+
bannerWaitSeconds?: number | undefined;
|
|
1493
|
+
configWarnings?: string[] | undefined;
|
|
1494
|
+
acceptSelectors?: string[] | undefined;
|
|
1495
|
+
rejectSelectors?: string[] | undefined;
|
|
1496
|
+
settingsSelectors?: string[] | undefined;
|
|
1497
|
+
bannerFrame?: string | undefined;
|
|
1498
|
+
license?: {
|
|
1499
|
+
entitled: boolean;
|
|
1500
|
+
reason?: "none" | "unreachable" | undefined;
|
|
1501
|
+
} | undefined;
|
|
1272
1502
|
}>;
|
|
1273
|
-
|
|
1503
|
+
/** Geparste Konfiguration (alle Defaults gesetzt). */
|
|
1504
|
+
type GateConfig = z.output<typeof GateConfigSchema>;
|
|
1505
|
+
/** Eingabe-Typ der öffentlichen API: Felder mit Default sind optional. */
|
|
1506
|
+
type GateConfigInput = z.input<typeof GateConfigSchema>;
|
|
1507
|
+
/**
|
|
1508
|
+
* Exit-Codes der CLI (in `--help` dokumentiert).
|
|
1509
|
+
*/
|
|
1510
|
+
declare const EXIT: {
|
|
1511
|
+
readonly OK: 0;
|
|
1512
|
+
/** Offene Leaks (BLOCKED), auch bei nur vorgeschlagenem, nicht verifiziertem Fix */
|
|
1513
|
+
readonly LEAKS: 1;
|
|
1514
|
+
/** Lizenz ungültig/abgelaufen/gesperrt (fehlende Lizenz oder nicht erreichbarer Lizenzserver nicht) */
|
|
1515
|
+
readonly LICENSE: 2;
|
|
1516
|
+
/** Fehler: Ziel unerreichbar, Konfiguration, Browser fehlt */
|
|
1517
|
+
readonly ERROR: 3;
|
|
1518
|
+
/** Unvollständig: Kernszenarien nicht prüfbar (INCONCLUSIVE) */
|
|
1519
|
+
readonly INCONCLUSIVE: 4;
|
|
1520
|
+
};
|
|
1521
|
+
/**
|
|
1522
|
+
* Vollständigkeit eines Scans: «nicht prüfbar» ist kein «bestanden».
|
|
1523
|
+
*/
|
|
1524
|
+
interface GateAssessment {
|
|
1525
|
+
/** Anzahl der geforderten Szenarien (z. B. 15) */
|
|
1526
|
+
scenariosTotal: number;
|
|
1527
|
+
/** Alle nicht prüfbaren Szenarien (inkl. «auffällig» mit Timeout/Fehler-Aktion) */
|
|
1528
|
+
uncheckable: ChaosScenario[];
|
|
1529
|
+
/** Davon Kernszenarien (Ablehnen-/Akzeptieren-Pfad, die den Banner bedienen) */
|
|
1530
|
+
coreUncheckable: ChaosScenario[];
|
|
1531
|
+
/** true, wenn kein Szenario nicht prüfbar ist und die Unterseiten-Stichprobe vollständig war */
|
|
1532
|
+
complete: boolean;
|
|
1533
|
+
/** Befundgruppen (Ursachen) statt Request-Zeilen — nur gate-blockierende Befunde */
|
|
1534
|
+
findingGroups: {
|
|
1535
|
+
ruleId: string;
|
|
1536
|
+
trackerName: string;
|
|
1537
|
+
count: number;
|
|
1538
|
+
}[];
|
|
1539
|
+
/** Hinweise (advisory), nicht gate-blockierend ausser mit `--strict` */
|
|
1540
|
+
advisoryGroups: {
|
|
1541
|
+
ruleId: string;
|
|
1542
|
+
trackerName: string;
|
|
1543
|
+
count: number;
|
|
1544
|
+
}[];
|
|
1545
|
+
/** Seite ohne Consent-Banner und ohne Tracker: es gibt nichts zu prüfen */
|
|
1546
|
+
noBannerNoTracker: boolean;
|
|
1547
|
+
/** Unterseiten-Stichprobe (Szenario subpage-spa), falls es lief */
|
|
1548
|
+
sampling?: SamplingInfo;
|
|
1549
|
+
}
|
|
1550
|
+
/** Unterseiten-Stichprobe: `checked` von `linked` geprüft; `incomplete`, wenn nicht alle verlinkten Unterseiten dran waren. */
|
|
1551
|
+
interface SamplingInfo {
|
|
1552
|
+
checked: number;
|
|
1553
|
+
linked: number;
|
|
1554
|
+
max: number;
|
|
1555
|
+
incomplete: boolean;
|
|
1556
|
+
}
|
|
1557
|
+
/**
|
|
1558
|
+
* Gate-Zustand: `clean` = PASS, `remediated` = Fix durch sauberen Re-Scan der Ziel-URL verifiziert,
|
|
1559
|
+
* `fix-proposed` = Fix als Commit/PR vorgeschlagen, aber nicht verifiziert (weiterhin BLOCKED).
|
|
1560
|
+
*/
|
|
1561
|
+
type GateState = "clean" | "remediated" | "blocked" | "inconclusive" | "fix-proposed";
|
|
1562
|
+
/** Gate-Zustand, wie ihn der Orchestrator führt — Eingabe für Report, Deckblatt und PDF. */
|
|
1563
|
+
interface ReportGate {
|
|
1564
|
+
state: GateState;
|
|
1565
|
+
scenariosTotal: number;
|
|
1566
|
+
/** Anzahl nicht prüfbarer Szenarien (laut Orchestrator) */
|
|
1567
|
+
uncheckable: number;
|
|
1568
|
+
coreUncheckable: ChaosScenario[];
|
|
1569
|
+
/** `--strict`: Hinweise zählen als Verstoss */
|
|
1570
|
+
strict?: boolean;
|
|
1571
|
+
noBannerNoTracker?: boolean;
|
|
1572
|
+
/** Vom Scanner gemeldet: wurde ein Consent-Banner gesehen? (undefined = unbekannt) */
|
|
1573
|
+
bannerObserved?: boolean;
|
|
1574
|
+
/** Warum «kein Banner» nicht belegt ist (Reload-Schleife, spät erschienen, nicht bedienbar) */
|
|
1575
|
+
bannerIssue?: BannerIssue;
|
|
1576
|
+
/** Unterseiten-Stichprobe (Szenario subpage-spa), falls es lief */
|
|
1577
|
+
sampling?: SamplingInfo;
|
|
1578
|
+
/** Warnungen des Scanners (z. B. ungültige Override-Selektoren) */
|
|
1579
|
+
scannerWarnings?: string[];
|
|
1580
|
+
/** `--ignore`-Muster, die sehr breit sind (nur mit `--allow-broad-ignore` überhaupt zulässig oder nur Warnung) */
|
|
1581
|
+
broadIgnore?: string[];
|
|
1582
|
+
/** Teilfix mit Commit/PR: so viele gemeldete Tracker bleiben manuell zu beheben */
|
|
1583
|
+
partialManual?: number;
|
|
1584
|
+
}
|
|
1274
1585
|
/**
|
|
1275
1586
|
* Overall pipeline outcome
|
|
1276
1587
|
*/
|
|
1277
1588
|
interface GateExecutionResult {
|
|
1278
1589
|
report: LeakReport;
|
|
1279
1590
|
remediation?: RemediationResult;
|
|
1280
|
-
status:
|
|
1591
|
+
status: GateState | "error";
|
|
1281
1592
|
exitCode: number;
|
|
1593
|
+
assessment?: GateAssessment;
|
|
1282
1594
|
}
|
|
1283
1595
|
|
|
1596
|
+
/** Für `--help`: die einzigen Schlüssel, die eine `.env` setzen darf. */
|
|
1597
|
+
declare const ENV_FILE_KEYS_HELP: string;
|
|
1598
|
+
declare function isEnvKeyAllowedFromFile(key: string): boolean;
|
|
1599
|
+
/**
|
|
1600
|
+
* Lädt eine `.env` aus dem Arbeitsverzeichnis in `process.env` — nur explizit aufgerufen (CLI),
|
|
1601
|
+
* nie als Import-Seiteneffekt. Die echte Umgebung gewinnt (wie bei dotenv); übernommen wird nur die Allowlist
|
|
1602
|
+
* (`isEnvKeyAllowedFromFile`).
|
|
1603
|
+
*/
|
|
1604
|
+
declare function loadProjectEnv(file?: string, env?: NodeJS.ProcessEnv): void;
|
|
1284
1605
|
interface CliRawOptions {
|
|
1285
1606
|
reportPdf?: boolean | string;
|
|
1286
1607
|
client?: string;
|
|
@@ -1289,8 +1610,11 @@ interface CliRawOptions {
|
|
|
1289
1610
|
apiKey?: string;
|
|
1290
1611
|
llmProvider?: string;
|
|
1291
1612
|
llmModel?: string;
|
|
1613
|
+
/** Opt-in: Quellcode darf an den LLM-Anbieter gesendet werden */
|
|
1614
|
+
llmRemediation?: string | boolean;
|
|
1292
1615
|
autoFix?: string | boolean;
|
|
1293
1616
|
failOnLeak?: string | boolean;
|
|
1617
|
+
failOnUncheckable?: string | boolean;
|
|
1294
1618
|
reportOutput?: string;
|
|
1295
1619
|
sourceDir?: string;
|
|
1296
1620
|
gitCommit?: string | boolean;
|
|
@@ -1300,128 +1624,311 @@ interface CliRawOptions {
|
|
|
1300
1624
|
baseBranch?: string;
|
|
1301
1625
|
headless?: string | boolean;
|
|
1302
1626
|
timeoutMs?: string | number;
|
|
1627
|
+
/** Szenarien-Auswahl: Array oder kommagetrennte Liste (leer = alle) */
|
|
1628
|
+
scenarios?: ChaosScenario[] | string[] | string;
|
|
1629
|
+
/** Rechtsraum: CH | EU | UK | US-CA | BR | ROW */
|
|
1630
|
+
jurisdiction?: string;
|
|
1631
|
+
/** Wird hier nicht ausgewertet — die Lizenzprüfung passiert in der CLI (src/cli.ts). */
|
|
1632
|
+
license?: string;
|
|
1633
|
+
/** Hinweise (advisory) blockieren ebenfalls */
|
|
1634
|
+
strict?: string | boolean;
|
|
1635
|
+
/** Sehr breite --ignore-Muster (`*`, `*.com`, einzelne TLD) bewusst erlauben */
|
|
1636
|
+
allowBroadIgnore?: string | boolean;
|
|
1637
|
+
/** Tracker-Namen oder Host-Muster, kommagetrennt oder mehrfach */
|
|
1638
|
+
ignore?: string[] | string;
|
|
1639
|
+
/** Scanner-Overrides: CSS-Selektoren, kommagetrennt oder mehrfach */
|
|
1640
|
+
acceptSelector?: string[] | string;
|
|
1641
|
+
rejectSelector?: string[] | string;
|
|
1642
|
+
settingsSelector?: string[] | string;
|
|
1643
|
+
/** Teilstring der URL des Banner-Frames (iframe-CMP) */
|
|
1644
|
+
bannerFrame?: string;
|
|
1645
|
+
/** Obergrenze der Unterseiten-Stichprobe (Standard 12, höchstens 40) */
|
|
1646
|
+
maxSubpages?: string | number;
|
|
1647
|
+
/** Wartefenster auf einen spät erscheinenden Banner in Sekunden (höchstens 60) */
|
|
1648
|
+
bannerWait?: string | number;
|
|
1303
1649
|
}
|
|
1650
|
+
/** Validiert eine Eingabe (Defaults werden gesetzt). Wirft «Invalid Configuration». */
|
|
1651
|
+
declare function parseGateConfig(input: GateConfigInput): GateConfig;
|
|
1304
1652
|
declare function resolveGateConfig(cliOptions: CliRawOptions): GateConfig;
|
|
1305
1653
|
|
|
1306
1654
|
interface ChaosScannerInterface {
|
|
1307
1655
|
scan(config: GateConfig): Promise<LeakReport>;
|
|
1308
1656
|
}
|
|
1309
1657
|
|
|
1310
|
-
/**
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
*/
|
|
1315
|
-
|
|
1316
|
-
/**
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1658
|
+
/** Optionale Vorgaben fuer Seiten mit unbekanntem Banner; werden VOR den Standardlisten ausgewertet. */
|
|
1659
|
+
interface ScannerOverrides {
|
|
1660
|
+
/** CSS-/Playwright-Selektoren fuer «Alle akzeptieren». */
|
|
1661
|
+
acceptSelectors?: string[];
|
|
1662
|
+
/** CSS-/Playwright-Selektoren fuer «Ablehnen» / «Nur notwendige». */
|
|
1663
|
+
rejectSelectors?: string[];
|
|
1664
|
+
/** CSS-/Playwright-Selektoren fuer «Einstellungen». */
|
|
1665
|
+
settingsSelectors?: string[];
|
|
1666
|
+
/** Teilstring der Frame-URL, in der der Banner liegt (cross-origin iframe-CMP). */
|
|
1667
|
+
bannerFrame?: string;
|
|
1668
|
+
/**
|
|
1669
|
+
* Das Wartefenster ausschöpfen, statt bei Seiten ohne Banner-Hinweis früh aufzugeben (`--banner-wait`). Gilt auch
|
|
1670
|
+
* ohne diese Angabe, sobald eigene Selektoren oder ein Banner-Frame angegeben sind: dann wird bis zum Ende gewartet.
|
|
1671
|
+
*/
|
|
1672
|
+
exhaustiveWait?: boolean;
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
interface ChaosScannerOptions extends ScannerOverrides {
|
|
1676
|
+
/** Zielverzeichnis fuer Screenshots (Default: `evidence/` neben dem Report aus der Config). */
|
|
1677
|
+
evidenceDir?: string;
|
|
1678
|
+
/** Obergrenze fuer die Gesamtgroesse der Screenshots eines Laufs in Bytes (Default 100 MB); darueber nur noch verkleinerte. */
|
|
1679
|
+
evidenceMaxBytes?: number;
|
|
1680
|
+
}
|
|
1321
1681
|
declare class ChaosScanner implements ChaosScannerInterface {
|
|
1682
|
+
private evidenceDir?;
|
|
1683
|
+
private readonly overrides;
|
|
1684
|
+
/** Bannersuche des laufenden Scans (Selektoren inkl. Overrides, «kein Banner» gemerkt). */
|
|
1685
|
+
private session;
|
|
1686
|
+
/** Navigation je Szenario (Fail-open-Schutz: Seite endete auf fremder Origin). */
|
|
1687
|
+
private watches;
|
|
1688
|
+
/** GTM-/gtag-Loader mit Consent Mode (default denied) ohne Messung ist kein Pre-Consent-Leak. */
|
|
1689
|
+
private gtmLoaderExempt;
|
|
1690
|
+
/** Hinweise zur Reichweite des Scans (Selektor-Fehler, spaet erschienener oder nicht bedienbarer Banner). */
|
|
1691
|
+
private warnings;
|
|
1692
|
+
/** Wartefenster auf einen Banner (ms) und ob es ausdruecklich gesetzt wurde (`--banner-wait`). */
|
|
1693
|
+
private bannerWaitMs;
|
|
1694
|
+
private bannerWaitExplicit;
|
|
1695
|
+
/** Obergrenze der Unterseiten-Stichprobe (`--max-subpages`). */
|
|
1696
|
+
private maxSubpages;
|
|
1697
|
+
/** Ergebnis der Schlusspruefung: nur `completed` belegt «kein Banner». */
|
|
1698
|
+
private bannerProbe;
|
|
1699
|
+
private bannerIssue?;
|
|
1700
|
+
private subpageSampling?;
|
|
1701
|
+
/** Bytes der in diesem Lauf geschriebenen Screenshots und deren Obergrenze. */
|
|
1702
|
+
private evidenceBytes;
|
|
1703
|
+
private evidenceCapNoted;
|
|
1704
|
+
private readonly evidenceMaxBytes;
|
|
1705
|
+
constructor(options?: ChaosScannerOptions);
|
|
1706
|
+
/** Die Schlusspruefung lief das Wartefenster vollstaendig ohne Banner-Hinweis durch (Seite stabil). */
|
|
1707
|
+
private probeCompleted;
|
|
1708
|
+
/** Overrides plus: das Wartefenster ausschoepfen, wenn `--banner-wait` ausdruecklich gesetzt ist. */
|
|
1709
|
+
private sessionOverrides;
|
|
1710
|
+
/** Beobachtung der Hauptseiten-Navigation fuer `scenario` merken (nachtraegliche Bewertung in scan()). */
|
|
1711
|
+
private remember;
|
|
1712
|
+
/** Verhalten eines erkannten Trackers: kein Befund (GTM-Loader mit Consent Mode), Hinweis oder Verstoss. */
|
|
1713
|
+
private trackerVerdict;
|
|
1714
|
+
/** `{ advisory: true }` fuer rein funktionale Treffer (Hinweis ohne Gate-Wirkung). */
|
|
1715
|
+
private advisoryFlag;
|
|
1716
|
+
/** Zaehlt ein Timeline-Ereignis als belastbarer Tracker-Befund (nicht advisory, nicht exempt). */
|
|
1717
|
+
private isBlocking;
|
|
1322
1718
|
scan(config: GateConfig): Promise<LeakReport>;
|
|
1719
|
+
/** Browser-Kontext mit blockierten Service Workern (deren Requests waeren unsichtbar) und Registrierungs-Beobachtung. */
|
|
1720
|
+
private newContext;
|
|
1721
|
+
/** Ungueltige Override-Selektoren (CSS-Syntaxfehler) werden gemeldet statt still verschluckt. */
|
|
1722
|
+
private checkOverrideSelectors;
|
|
1723
|
+
/**
|
|
1724
|
+
* Schlusspruefung: War bis hierhin kein Banner sichtbar, laedt ein frischer Kontext die Zielseite und wartet
|
|
1725
|
+
* ueber das normale Wartefenster hinaus. Erscheint ein Banner erst spaeter (Timer, langsames CMP), gilt
|
|
1726
|
+
* «kein Banner» nicht — `bannerObserved` wird `true`, mit Hinweis.
|
|
1727
|
+
*/
|
|
1728
|
+
private probeLateBanner;
|
|
1729
|
+
/** Hinweise zum Banner-Zustand und zu nie verwendeten Override-Selektoren in `scannerWarnings`. */
|
|
1730
|
+
private reportBannerState;
|
|
1323
1731
|
private snapshotStorage;
|
|
1732
|
+
/**
|
|
1733
|
+
* Navigiert zur Ziel-URL und fuehrt den Zielbereich nach: die finale URL (nach Redirects)
|
|
1734
|
+
* gehoert zum Ziel, auch wenn sie auf einer anderen Origin liegt. Navigiert die Seite selbst
|
|
1735
|
+
* weiter (`<meta refresh>`, `location.replace`), wird auf die neue Seite gewartet statt abzubrechen.
|
|
1736
|
+
* Fehlermeldungen nennen die konfigurierte Ursprungs-URL, nicht nur das Weiterleitungsziel.
|
|
1737
|
+
*/
|
|
1738
|
+
private gotoTarget;
|
|
1739
|
+
/**
|
|
1740
|
+
* Scanner-Navigation zu einer verlinkten Unterseite: deren Weiterleitungen erweitern den Zielbereich nicht.
|
|
1741
|
+
* Laufende Navigationen der vorigen Seite werden abgewartet; leitet die Unterseite selbst clientseitig weiter
|
|
1742
|
+
* («interrupted by another navigation»), gilt der HTTP-Status der Endseite statt eines Abbruchs.
|
|
1743
|
+
*/
|
|
1744
|
+
private gotoSubpage;
|
|
1745
|
+
/**
|
|
1746
|
+
* Consent Mode: Setzt die Seite VOR dem GTM-/gtag-Laden `consent default denied` und findet vor
|
|
1747
|
+
* Consent keine Messung statt (keine Collect-/Pixel-Requests, keine Tracking-Cookies), ist der reine
|
|
1748
|
+
* Skript-Load des Loaders kein Pre-Consent-Leak. Ohne Consent Mode bleibt er ein Verstoss.
|
|
1749
|
+
*/
|
|
1750
|
+
private probeGtmConsentMode;
|
|
1751
|
+
/** Rein funktionale Drittanbieter (z. B. Google Fonts) in der Timeline: als Hinweis in der Notiz vermerken. */
|
|
1752
|
+
private annotateAdvisory;
|
|
1753
|
+
/** Steht (jetzt) irgendein Consent-Banner im DOM der Zielseite? Merkt es fuer `bannerObserved`. */
|
|
1754
|
+
private noteBannerHints;
|
|
1755
|
+
/**
|
|
1756
|
+
* Fail-open-Schutz: Lief ein Szenario ganz oder teilweise auf einer fremden Seite (Requests wurden
|
|
1757
|
+
* dem Ziel nicht zugerechnet), ist ein «bestanden» nicht belastbar — dann «nicht prüfbar» mit Begruendung.
|
|
1758
|
+
*/
|
|
1759
|
+
private applyScopeVerdicts;
|
|
1324
1760
|
/**
|
|
1325
1761
|
* Fünf Kern-Chaos-Szenarien mit vollständigem Evidence-Record.
|
|
1326
1762
|
* Phasen statt Capture-Wipe: Pre-Consent-Funde bleiben immer erhalten.
|
|
1327
1763
|
* Ergebnis: passed nur bei ausgeführter Aktion und null Illegal-Funden.
|
|
1328
1764
|
*/
|
|
1329
1765
|
private runScenario;
|
|
1766
|
+
/**
|
|
1767
|
+
* Kein Ablehnen-Button gefunden: ist das ein Dark Pattern oder nur ein nicht erkannter Banner?
|
|
1768
|
+
* Sehr konservativ — «Banner nicht erkannt» wird nie als Dark Pattern gemeldet. Ein Befund
|
|
1769
|
+
* (`no-reject-option`) entsteht nur, wenn (1) auf der ersten Ebene ein Accept erkannt ist,
|
|
1770
|
+
* (2) der Banner eindeutig als Cookie-Dialog erkennbar ist und ausser Accept nur Einstellungen/
|
|
1771
|
+
* Infolinks enthaelt, (3) auch die Einstellungen (zweite Ebene) keinen Ablehnen-Weg bieten und
|
|
1772
|
+
* (4) Tracking im Spiel ist (vor der Entscheidung oder nach dem Akzeptieren).
|
|
1773
|
+
* `rejected`: ein Ablehnen-Weg wurde auf der zweiten Ebene gefunden und geklickt.
|
|
1774
|
+
*/
|
|
1775
|
+
private assessMissingReject;
|
|
1330
1776
|
private snap;
|
|
1331
|
-
private logAct;
|
|
1332
1777
|
/**
|
|
1333
|
-
*
|
|
1334
|
-
*
|
|
1335
|
-
*
|
|
1778
|
+
* Screenshot fuer den Evidence-Ordner: Breite = Viewport, hoechstens SHOT_MAX_HEIGHT hoch, JPEG. Bleibt die Datei ueber
|
|
1779
|
+
* SHOT_MAX_BYTES, wird mit sinkender Qualitaet und Hoehe erneut aufgenommen. Ist der evidence-Ordner des Laufs voll
|
|
1780
|
+
* (evidenceMaxBytes), entstehen nur noch verkleinerte Aufnahmen, mit Hinweis in den Scanner-Warnungen.
|
|
1336
1781
|
*/
|
|
1782
|
+
private captureShot;
|
|
1783
|
+
/** Bricht eine noch laufende Navigation ab (Chrome `Page.stopLoading`), ohne auf deren Antwort zu warten. */
|
|
1784
|
+
private stopLoading;
|
|
1785
|
+
private logAct;
|
|
1337
1786
|
/**
|
|
1338
1787
|
* Kategorien-Granularität: Statistik erlaubt, Marketing abgelehnt.
|
|
1339
|
-
* Marketing-Tracker (Meta, TikTok, LinkedIn, Criteo
|
|
1340
|
-
*
|
|
1788
|
+
* Marketing-Tracker (Meta, TikTok, LinkedIn, Criteo, …) dürfen danach NICHT feuern.
|
|
1789
|
+
* Ohne Kategorie-UI, ohne belegt abgewähltes Marketing oder ohne Speichern-Button —
|
|
1790
|
+
* status «not-checkable» (nie «Alle akzeptieren» als Ersatz).
|
|
1341
1791
|
*/
|
|
1342
1792
|
private runCategorySelectiveScenario;
|
|
1343
1793
|
/**
|
|
1344
|
-
* Entscheidung merken: nach «Ablehnen» Reload,
|
|
1345
|
-
* (storageState). Tracker müssen ausbleiben, die Entscheidung muss erhalten
|
|
1794
|
+
* Entscheidung merken: nach «Ablehnen» Reload, Unterseite (echter verlinkter Pfad) und
|
|
1795
|
+
* Browser-Neustart (storageState). Tracker müssen ausbleiben, die Entscheidung muss erhalten
|
|
1796
|
+
* bleiben. Ohne erreichbare Unterseite ist die Persistenz nicht vollständig belegt — «not-checkable».
|
|
1346
1797
|
*/
|
|
1347
1798
|
private runPersistenceScenario;
|
|
1348
1799
|
/**
|
|
1349
|
-
*
|
|
1350
|
-
*
|
|
1351
|
-
*/
|
|
1352
|
-
/**
|
|
1353
|
-
* Unterseiten & SPA: Direkteinstieg auf Subpage, dann Client-Navigation ohne Reload.
|
|
1354
|
-
* Consent-Schutz muss auch dort greifen.
|
|
1355
|
-
*/
|
|
1356
|
-
/**
|
|
1357
|
-
* CMP langsam oder defekt: CMP-Skripte verzögern/abbringen, dann beobachten,
|
|
1358
|
-
* ob im Zeitfenster Tracker starten (Default-State-Leak).
|
|
1800
|
+
* Mobile: iPhone-Viewport. Reject und Settings müssen sichtbar und klickbar sein.
|
|
1801
|
+
* Nur Accept bedienbar — suspicious (Dark Pattern); keine Buttons — not-checkable.
|
|
1359
1802
|
*/
|
|
1803
|
+
private runMobileUsabilityScenario;
|
|
1360
1804
|
/**
|
|
1361
|
-
*
|
|
1362
|
-
*
|
|
1805
|
+
* Doppelte Events: ein Seitenaufruf nach Consent darf page_view nicht doppelt zählen
|
|
1806
|
+
* (Plugin + GTM parallel) — je Property (GA4 `tid`, Pixel `id`, …): mehrere Properties mit je
|
|
1807
|
+
* einem Beacon sind kein Duplikat. Ohne belegten Accept-Klick ist der Consent-Zustand nicht
|
|
1808
|
+
* hergestellt — «not-checkable». First-Party-Heuristik: verdächtige same-origin Endpunkte
|
|
1809
|
+
* (collect, pixel, track) werden markiert — Server-zu-Server ist von aussen begrenzt beweisbar.
|
|
1363
1810
|
*/
|
|
1811
|
+
private runDuplicateEventsScenario;
|
|
1364
1812
|
/**
|
|
1365
|
-
* Consent Mode v2: dataLayer-Konsens-Zustände (ad_storage, analytics_storage,
|
|
1813
|
+
* Consent Mode v2: dataLayer-Konsens-Zustände (ad_storage, analytics_storage, …)
|
|
1366
1814
|
* gegen tatsächliche Google-Requests und Cookies trennen.
|
|
1367
1815
|
* Bei Basic dürfen nach Ablehnung keine Nutzungsdaten laufen; bei Advanced
|
|
1368
1816
|
* sind cookielose Pings möglich — beides wird getrennt ausgewiesen.
|
|
1369
1817
|
*/
|
|
1818
|
+
private runConsentModeV2Scenario;
|
|
1370
1819
|
/**
|
|
1371
|
-
*
|
|
1372
|
-
*
|
|
1373
|
-
*
|
|
1820
|
+
* Eingebettete Inhalte (YouTube, Maps, Social): Drittanbieter-Requests vor Consent-Freigabe
|
|
1821
|
+
* des Embeds. Als Embed gilt nur, was die Tracker-Datenbank als Embed-Kategorie fuehrt —
|
|
1822
|
+
* nicht per Namens-Regex (sonst wuerde z. B. das Meta Pixel als «Embed» klassifiziert).
|
|
1374
1823
|
*/
|
|
1824
|
+
private runEmbedScenario;
|
|
1375
1825
|
/**
|
|
1376
|
-
*
|
|
1377
|
-
*
|
|
1826
|
+
* CMP langsam oder defekt: CMP-Ressourcen (auch same-origin, self-hosted) verzögern, dann
|
|
1827
|
+
* hart abbrechen, und beobachten, ob im Zeitfenster Tracker starten (Default-State-Leak).
|
|
1828
|
+
* Ohne abgefangene CMP-Ressource gibt es keinen Nachweis eines verzögerten CMPs —
|
|
1829
|
+
* dann «not-checkable» statt «passed».
|
|
1378
1830
|
*/
|
|
1379
|
-
private runMobileUsabilityScenario;
|
|
1380
|
-
private runDuplicateEventsScenario;
|
|
1381
|
-
private runConsentModeV2Scenario;
|
|
1382
|
-
private runEmbedScenario;
|
|
1383
1831
|
private runCmpFailureScenario;
|
|
1832
|
+
/** Seite, auf der ein Request ausgelöst wurde (für Befunde auf Unterseiten); leer, wenn nicht ermittelbar. */
|
|
1833
|
+
private pageHint;
|
|
1834
|
+
/**
|
|
1835
|
+
* Unterseiten & SPA: echte, auf der Startseite verlinkte Same-Origin-Pfade (HTTP-Status geprüft)
|
|
1836
|
+
* als Direkteinstieg, danach clientseitige Navigation (Link-Klick ohne Dokument-Reload,
|
|
1837
|
+
* History-API) beobachten. Es wird kein Consent erteilt — jeder Tracker ist ein Verstoss.
|
|
1838
|
+
* Ohne erreichbare verlinkte Unterseite «not-checkable» (erfundene Pfade ergeben keinen Beleg).
|
|
1839
|
+
*/
|
|
1384
1840
|
private runSubpageSpaScenario;
|
|
1841
|
+
/**
|
|
1842
|
+
* Banner ignorieren: kein Klick auf den Banner, nur warten, scrollen, auf freie Flaeche tippen.
|
|
1843
|
+
* Tracker dürfen nicht über Timer/Scroll/Input allein starten.
|
|
1844
|
+
*/
|
|
1385
1845
|
private runBannerIgnoredScenario;
|
|
1846
|
+
/**
|
|
1847
|
+
* Widerruf: erst akzeptieren, dann widerrufen. Prüft (a) keine neuen Tracker-Requests
|
|
1848
|
+
* nach Widerruf, (b) ob Tracking-IDs in Cookies/Storage zurückbleiben.
|
|
1849
|
+
* Kein Widerruf-Button — status «not-checkable» (nie grün).
|
|
1850
|
+
*/
|
|
1386
1851
|
private runRevocationScenario;
|
|
1387
1852
|
}
|
|
1388
1853
|
|
|
1854
|
+
/** patched = no unguarded execution left; manual = an auto-fix exists but could not be applied here; unpatched = no auto-fix. */
|
|
1855
|
+
type TrackerPatchState = "patched" | "unpatched" | "manual";
|
|
1856
|
+
interface TrackerStatus {
|
|
1857
|
+
trackerName: string;
|
|
1858
|
+
state: TrackerPatchState;
|
|
1859
|
+
/** Why the tracker is not (fully) patched, or what was done; German, shown to the user. */
|
|
1860
|
+
reason?: string;
|
|
1861
|
+
}
|
|
1862
|
+
/**
|
|
1863
|
+
* RemediationResult plus what the caller needs to stay honest about partial fixes. Structurally a
|
|
1864
|
+
* RemediationResult (all additions are optional), so existing consumers keep working.
|
|
1865
|
+
*/
|
|
1866
|
+
interface RemediationOutcome extends RemediationResult {
|
|
1867
|
+
/**
|
|
1868
|
+
* Also set for a partial fix (`partial: true`, `success: false`) whenever the approved patches were committed or
|
|
1869
|
+
* pushed: `commitHash` (short hash of the commit, `gitCommit`), `pullRequest` (PR result incl. `branchName`, `createPr`)
|
|
1870
|
+
* and `branchName` (the fix branch of the PR, a copy of `pullRequest.branchName`). A consumer must not read
|
|
1871
|
+
* `success` as "nothing was written": check these fields.
|
|
1872
|
+
*/
|
|
1873
|
+
branchName?: string;
|
|
1874
|
+
/** Some patches were applied, but not every reported tracker is covered: do NOT treat the gate as fixed. */
|
|
1875
|
+
partial?: boolean;
|
|
1876
|
+
/** Part of the fix has to be done by hand (unpatched trackers, unsupported consent platform, entangled code). */
|
|
1877
|
+
manual?: boolean;
|
|
1878
|
+
/** Reported trackers that are not covered by a patch (state "unpatched" | "manual"). */
|
|
1879
|
+
unpatched?: TrackerStatus[];
|
|
1880
|
+
/** Status of every reported tracker name. */
|
|
1881
|
+
trackerStatus?: TrackerStatus[];
|
|
1882
|
+
/** Supported consent platforms (OneTrust, Cookiebot) found in the source: their category consent is read automatically, no hook needed. */
|
|
1883
|
+
cmpSupported?: string[];
|
|
1884
|
+
/** How a custom consent banner talks to the injected runtime (code lines, ready to paste). */
|
|
1885
|
+
integrationHooks?: string[];
|
|
1886
|
+
/** Plain-text instructions for PR body and console: what to fix by hand, and the consent hooks. */
|
|
1887
|
+
manualSteps?: string;
|
|
1888
|
+
/** Hint when a requested commit/PR could not be made (e.g. the source dir is in no git repository); the fix stays local. */
|
|
1889
|
+
gitNote?: string;
|
|
1890
|
+
}
|
|
1389
1891
|
interface RemediationEngineInterface {
|
|
1390
|
-
remediate(report: LeakReport, config: GateConfig): Promise<
|
|
1892
|
+
remediate(report: LeakReport, config: GateConfig): Promise<RemediationOutcome>;
|
|
1391
1893
|
}
|
|
1392
1894
|
|
|
1393
1895
|
interface CodeReviewerInterface {
|
|
1394
1896
|
review(patches: FilePatch[], report: LeakReport, config: GateConfig): Promise<ReviewVerdict>;
|
|
1395
1897
|
}
|
|
1396
1898
|
|
|
1899
|
+
/** What the fix does NOT cover and how a custom consent banner talks to the injected runtime. */
|
|
1900
|
+
interface PullRequestExtras {
|
|
1901
|
+
unpatched?: TrackerStatus[];
|
|
1902
|
+
integrationHooks?: string[];
|
|
1903
|
+
/** Set when a supported CMP (OneTrust, Cookiebot) was recognised: it is read automatically, no hook is needed. */
|
|
1904
|
+
consentNote?: string;
|
|
1905
|
+
}
|
|
1397
1906
|
declare class PullRequestEngine {
|
|
1398
1907
|
private git;
|
|
1399
1908
|
/**
|
|
1400
1909
|
* Creates a fix branch, commits only the given files, pushes and opens a PR when a remote + token exist.
|
|
1401
1910
|
* Always returns to the starting branch. Throws on any git/API failure (caller restores the working tree).
|
|
1402
1911
|
*/
|
|
1403
|
-
createPullRequest(patches: FilePatch[], report: LeakReport, reviewVerdict: ReviewVerdict, config: GateConfig): Promise<PullRequestResult>;
|
|
1912
|
+
createPullRequest(patches: FilePatch[], report: LeakReport, reviewVerdict: ReviewVerdict, config: GateConfig, extras?: PullRequestExtras): Promise<PullRequestResult>;
|
|
1404
1913
|
private resolveBaseBranch;
|
|
1405
|
-
buildPrDescription(report: LeakReport, reviewVerdict: ReviewVerdict, patches: FilePatch[], config: GateConfig): string;
|
|
1914
|
+
buildPrDescription(report: LeakReport, reviewVerdict: ReviewVerdict, patches: FilePatch[], config: GateConfig, extras?: PullRequestExtras): string;
|
|
1406
1915
|
}
|
|
1407
1916
|
|
|
1408
|
-
/**
|
|
1409
|
-
* Injected when trackers are deferred. Activates `script[type=text/plain][data-src]`
|
|
1410
|
-
* and runs registered inits once consent is granted — including late accept clicks.
|
|
1411
|
-
*/
|
|
1412
|
-
declare const CONSENT_ACTIVATION_RUNTIME = "<script data-cpcg=\"consent-activation\">\n(function () {\n if (window.__cpcgConsentRuntime) return;\n window.__cpcgConsentRuntime = true;\n window.__cpcgInits = window.__cpcgInits || [];\n\n function cpcgHasConsent() {\n try {\n var raw;\n // Explicit hook for custom CMPs\n if (window.__cpcgConsentGranted === true) return true;\n // Our own / simple stores\n raw = localStorage.getItem(\"cpcg_consent\");\n if (raw === \"accepted\") return true;\n raw = localStorage.getItem(\"consent\");\n if (raw === \"accepted\") return true;\n raw = localStorage.getItem(\"usercentrics-consent\");\n if (raw === \"accepted\") return true;\n // OneTrust: OptanonConsent is a URL-encoded query string (has consentId, groups=\u2026)\n raw = localStorage.getItem(\"OptanonConsent\");\n if (raw) {\n if (raw === \"accepted\") return true;\n try {\n var q = new URLSearchParams(raw);\n if (q.get(\"status\") === \"accepted\" || q.get(\"groups\") && q.get(\"groups\").indexOf(\":1\") !== -1) return true;\n if (q.has(\"consentId\") && !/isIabGlobal=false;status=-1/.test(raw)) return true;\n } catch (e) {}\n }\n // Cookiebot: JSON with consented / stamp\n raw = localStorage.getItem(\"CookieConsent\");\n if (raw) {\n if (raw === \"accepted\" || raw === \"true\") return true;\n try {\n var cb = JSON.parse(raw);\n if (cb && (cb.consented === true || cb.necessary === true || cb.stamp)) return true;\n } catch (e) {}\n }\n // OneTrust OptanonConsent cookie fallback\n if (/(^|;s*)OptanonConsent=/.test(document.cookie)) return true;\n return false;\n } catch (_) {\n return false;\n }\n }\n\n function cpcgActivateDeferred() {\n if (!cpcgHasConsent()) return false;\n document.querySelectorAll('script[type=\"text/plain\"][data-src]').forEach(function (old) {\n if (old.getAttribute(\"data-cpcg-activated\") === \"1\") return;\n old.setAttribute(\"data-cpcg-activated\", \"1\");\n var s = document.createElement(\"script\");\n s.src = old.getAttribute(\"data-src\");\n s.async = old.async !== false;\n if (old.getAttribute(\"data-cookiecategory\")) {\n s.setAttribute(\"data-cookiecategory\", old.getAttribute(\"data-cookiecategory\"));\n }\n old.parentNode.insertBefore(s, old.nextSibling);\n });\n (window.__cpcgInits || []).forEach(function (fn) {\n try { fn(); } catch (e) { /* init failed */ }\n });\n window.__cpcgInits = [];\n return true;\n }\n\n window.cpcgActivateTrackers = cpcgActivateDeferred;\n window.cpcgGrantConsent = function () {\n window.__cpcgConsentGranted = true;\n return cpcgActivateDeferred();\n };\n\n [\"click\", \"storage\", \"consent\", \"usercentrics-consent\", \"OneTrustLoaded\"].forEach(function (evt) {\n window.addEventListener(evt, function () {\n setTimeout(cpcgActivateDeferred, 50);\n }, true);\n });\n document.addEventListener(\"click\", function () {\n setTimeout(cpcgActivateDeferred, 50);\n }, true);\n\n // Late accept: poll briefly while the page is open\n var tries = 0;\n var timer = setInterval(function () {\n tries += 1;\n if (cpcgActivateDeferred() || tries > 40) clearInterval(timer);\n }, 500);\n\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", cpcgActivateDeferred);\n } else {\n cpcgActivateDeferred();\n }\n})();\n</script>";
|
|
1413
1917
|
declare class RemediationEngine implements RemediationEngineInterface {
|
|
1414
1918
|
private reviewer;
|
|
1415
1919
|
private prEngine;
|
|
1416
1920
|
constructor(reviewer?: CodeReviewerInterface, prEngine?: PullRequestEngine);
|
|
1417
|
-
remediate(report: LeakReport, config: GateConfig): Promise<
|
|
1921
|
+
remediate(report: LeakReport, config: GateConfig): Promise<RemediationOutcome>;
|
|
1418
1922
|
private findCandidateSourceFiles;
|
|
1419
1923
|
/**
|
|
1420
|
-
* Deterministic Privacy Patcher:
|
|
1924
|
+
* Deterministic Privacy Patcher: defers tracker execution until category consent.
|
|
1925
|
+
* HTML is patched script block by script block (everything else stays byte-identical); SPA sources get
|
|
1926
|
+
* consent guards. Anything that cannot be patched safely is returned as a manual instruction instead.
|
|
1421
1927
|
*/
|
|
1422
1928
|
private remediateWithRuleEngine;
|
|
1423
1929
|
/**
|
|
1424
|
-
* LLM API Remediation
|
|
1930
|
+
* LLM API Remediation (OpenAI only, explicit opt-in checked by the caller): generates surgical code patches
|
|
1931
|
+
* for the files that actually reference the leaking tracker. Page-controlled strings are delimited as untrusted.
|
|
1425
1932
|
*/
|
|
1426
1933
|
private remediateWithLlm;
|
|
1427
1934
|
/**
|
|
@@ -1431,12 +1938,61 @@ declare class RemediationEngine implements RemediationEngineInterface {
|
|
|
1431
1938
|
private sanitizeLlmPatches;
|
|
1432
1939
|
}
|
|
1433
1940
|
|
|
1941
|
+
/**
|
|
1942
|
+
* Kernszenarien: Ablehnen- und Akzeptieren-Pfad bedienen den Banner.
|
|
1943
|
+
* Sind sie nicht prüfbar, sagt der Scan über Consent nichts aus — das Gate darf dann nicht PASS melden.
|
|
1944
|
+
*/
|
|
1945
|
+
declare const CORE_SCENARIOS: readonly ChaosScenario[];
|
|
1946
|
+
/** Gruppiert Befunde zu Befundgruppen (Regel + Tracker). */
|
|
1947
|
+
declare function groupFindings(violations: {
|
|
1948
|
+
ruleId?: string;
|
|
1949
|
+
trackerName: string;
|
|
1950
|
+
}[]): {
|
|
1951
|
+
key: string;
|
|
1952
|
+
ruleId: string;
|
|
1953
|
+
trackerName: string;
|
|
1954
|
+
count: number;
|
|
1955
|
+
}[];
|
|
1956
|
+
/** Bewertet die Vollständigkeit des Scans. */
|
|
1957
|
+
declare function assessReport(report: LeakReport, scenarios?: ChaosScenario[], options?: {
|
|
1958
|
+
strict?: boolean;
|
|
1959
|
+
}): GateAssessment;
|
|
1960
|
+
|
|
1961
|
+
/** Prüft, ob die Zielseite antwortet und nicht mit 4xx/5xx; wirft sonst einen neutralen Fehler. */
|
|
1962
|
+
declare function checkTargetReachable(url: string, timeoutMs: number, fetchImpl?: typeof fetch): Promise<number>;
|
|
1963
|
+
type Preflight = (config: GateConfig) => Promise<unknown>;
|
|
1964
|
+
/** Lizenzpflichtige Funktionen, die in diesem Lauf angefordert wurden (Bezeichnung für Konsole/Summary). */
|
|
1965
|
+
declare function requestedLicensedFeatures(config: GateConfig): string[];
|
|
1966
|
+
/** Hinweistext, warum lizenzpflichtige Funktionen nicht liefen; nennt die konkret übersprungene Funktion. */
|
|
1967
|
+
declare function licenseSkipText(config: GateConfig, skipped: string[]): string;
|
|
1968
|
+
/**
|
|
1969
|
+
* Gründe, warum Szenarien nicht prüfbar sind, aus deren Notiz («Nicht prüfbar: <Grund> (zuvor: …)» bzw.
|
|
1970
|
+
* «Szenario nicht prüfbar — <Grund> (kein grünes Häkchen)»); identische Gründe stehen einmal mit allen Szenarien.
|
|
1971
|
+
*/
|
|
1972
|
+
declare function uncheckableReasons(report: LeakReport, scenarios: ChaosScenario[]): {
|
|
1973
|
+
reason: string;
|
|
1974
|
+
scenarios: ChaosScenario[];
|
|
1975
|
+
}[];
|
|
1434
1976
|
declare class PrivacyChaosGate {
|
|
1435
|
-
private scanner
|
|
1977
|
+
private scanner?;
|
|
1436
1978
|
private remediationEngine;
|
|
1437
|
-
|
|
1438
|
-
|
|
1979
|
+
private preflight?;
|
|
1980
|
+
/**
|
|
1981
|
+
* @param preflight Erreichbarkeits-Check vor dem Scan. Default: HTTP-Check (nur mit dem Standard-Scanner);
|
|
1982
|
+
* wer einen eigenen Scanner injiziert, ist selbst für die Zielseite zuständig.
|
|
1983
|
+
*/
|
|
1984
|
+
constructor(scanner?: ChaosScannerInterface, remediationEngine?: RemediationEngineInterface, preflight?: Preflight);
|
|
1985
|
+
run(input: GateConfigInput): Promise<GateExecutionResult>;
|
|
1986
|
+
private printExitNotes;
|
|
1987
|
+
/** Aussage zum Re-Scan, ohne mehr zu behaupten als gemessen wurde. */
|
|
1988
|
+
private rescanNote;
|
|
1989
|
+
private proposalOf;
|
|
1990
|
+
/** Hinweise zu einem lokal angelegten Fix-Branch (kein Token/Remote): wo der Fix liegt, ob der Arbeitsbaum geändert ist. */
|
|
1991
|
+
private localBranchNotes;
|
|
1992
|
+
private proposalText;
|
|
1439
1993
|
private saveReport;
|
|
1994
|
+
/** Komprimierte Fassungen (data-URI) für die Screenshots, sobald deren Gesamtgrösse einbettungsrelevant ist. */
|
|
1995
|
+
private embeddableScreenshots;
|
|
1440
1996
|
private writeGitHubOutputs;
|
|
1441
1997
|
private writeGitHubSummary;
|
|
1442
1998
|
}
|
|
@@ -1448,9 +2004,16 @@ declare class PrivacyChaosGate {
|
|
|
1448
2004
|
*/
|
|
1449
2005
|
interface EvidenceMarkdownOptions {
|
|
1450
2006
|
demo?: boolean;
|
|
2007
|
+
/** Gate-Zustand aus dem Orchestrator; ohne Angabe wird er nur aus den Befunden abgeleitet. */
|
|
2008
|
+
gate?: ReportGate;
|
|
2009
|
+
/** Kundenname (Kundenreport) */
|
|
2010
|
+
client?: string;
|
|
1451
2011
|
}
|
|
2012
|
+
|
|
1452
2013
|
/** Status-Lesart für beide Renderer — eine Quelle, kein Drift. */
|
|
1453
2014
|
declare function statusLabelOf(s: EvidenceRecord["status"]): string;
|
|
2015
|
+
/** Status eines Szenarios samt Zusatz: «bestanden (Befunde ignoriert)», wenn alle seine Befunde per --ignore ausgenommen wurden. */
|
|
2016
|
+
declare function evidenceLabelOf(e: EvidenceRecord): string;
|
|
1454
2017
|
/** Zählung und Gate-Text — von Markdown und HTML gemeinsam genutzt. */
|
|
1455
2018
|
interface ReportFacts {
|
|
1456
2019
|
evidenceCount: number;
|
|
@@ -1459,9 +2022,22 @@ interface ReportFacts {
|
|
|
1459
2022
|
uncheckable: number;
|
|
1460
2023
|
notApplicable: number;
|
|
1461
2024
|
incomplete: number;
|
|
2025
|
+
/** Gate-blockierende Befunde (Request-Zeilen); Hinweise stehen in `advisory` */
|
|
1462
2026
|
findings: number;
|
|
2027
|
+
advisory: number;
|
|
2028
|
+
ignored: number;
|
|
1463
2029
|
observedCount: number;
|
|
1464
|
-
|
|
2030
|
+
/** Kurzlabel: PASS | BLOCKED | UNVOLLSTÄNDIG */
|
|
2031
|
+
gate: "PASS" | "BLOCKED" | "UNVOLLSTÄNDIG";
|
|
2032
|
+
gateState: GateState;
|
|
2033
|
+
/** Volltext hinter «Technisches Gate: » (z. B. «UNVOLLSTÄNDIG — 2 von 15 Szenarien nicht prüfbar») */
|
|
2034
|
+
gateHeadline: string;
|
|
2035
|
+
/** Ton der Gate-Karte: ok | blocked | warn */
|
|
2036
|
+
gateTone: "ok" | "blocked" | "warn";
|
|
2037
|
+
/** Geprüft = bestanden + auffällig; nicht prüfbar laut Orchestrator (sonst aus den Nachweisen) */
|
|
2038
|
+
checked: number;
|
|
2039
|
+
uncheckableTotal: number;
|
|
2040
|
+
scenariosTotal?: number;
|
|
1465
2041
|
findingsText: string;
|
|
1466
2042
|
gateDisclaimer: string;
|
|
1467
2043
|
problemCount: number;
|
|
@@ -1475,28 +2051,34 @@ interface CodeSolution {
|
|
|
1475
2051
|
code: string;
|
|
1476
2052
|
}
|
|
1477
2053
|
/** Nur Regeln mit belegtem Befund bekommen eine Code-Lösung. */
|
|
1478
|
-
declare function codeSolutionsFor(report: LeakReport): CodeSolution[];
|
|
1479
|
-
declare function deriveReportFacts(report: LeakReport): ReportFacts;
|
|
2054
|
+
declare function codeSolutionsFor(report: LeakReport, strict?: boolean): CodeSolution[];
|
|
2055
|
+
declare function deriveReportFacts(report: LeakReport, gate?: ReportGate): ReportFacts;
|
|
2056
|
+
/** Gate-Zustand für Deckblatt/PDF: dieselbe Ableitung wie im Report. */
|
|
2057
|
+
declare function resolveReportGate(report: LeakReport, gate?: ReportGate): ReportFacts;
|
|
2058
|
+
/**
|
|
2059
|
+
* Zusatzhinweise zum Gate-Zustand (Banner nicht erkannt, Teilfix, Scanner-Warnungen, breites Ignore-Muster).
|
|
2060
|
+
* Eine Quelle für Markdown, HTML und Deckblatt.
|
|
2061
|
+
*/
|
|
2062
|
+
declare function gateNotesOf(gate: ReportGate | undefined): {
|
|
2063
|
+
state: string;
|
|
2064
|
+
warnings: string[];
|
|
2065
|
+
};
|
|
1480
2066
|
/** 1 Befund-Zeile / N Befund-Zeilen — nie «Befund-Zeile(n)». */
|
|
1481
2067
|
declare function findingsCountText(n: number): string;
|
|
1482
2068
|
/** Kundennutzen: Befundgruppen statt Request-Zeilen. */
|
|
1483
2069
|
declare function problemsTextOf(n: number): string;
|
|
1484
|
-
/** Gruppiert Befunde zu Befundgruppen (Regel + Tracker). */
|
|
1485
|
-
declare function groupFindings(violations: {
|
|
1486
|
-
ruleId?: string;
|
|
1487
|
-
trackerName: string;
|
|
1488
|
-
}[]): {
|
|
1489
|
-
key: string;
|
|
1490
|
-
ruleId: string;
|
|
1491
|
-
trackerName: string;
|
|
1492
|
-
count: number;
|
|
1493
|
-
}[];
|
|
1494
2070
|
/** Zähltext: Requests, nicht vage «×». */
|
|
1495
2071
|
declare function reproductionText(count: number): string;
|
|
1496
2072
|
declare function buildEvidenceMarkdown(report: LeakReport, title?: string, options?: EvidenceMarkdownOptions): string;
|
|
1497
2073
|
interface EvidenceHtmlOptions {
|
|
1498
2074
|
/** Demo-Lauf mit synthetischen Testdaten klar kennzeichnen */
|
|
1499
2075
|
demo?: boolean;
|
|
2076
|
+
/** Gate-Zustand aus dem Orchestrator; ohne Angabe wird er nur aus den Befunden abgeleitet. */
|
|
2077
|
+
gate?: ReportGate;
|
|
2078
|
+
/** Kundenname (Kundenreport) */
|
|
2079
|
+
client?: string;
|
|
2080
|
+
/** Komprimierte Fassungen der Screenshots (Originalpfad → data-URI), siehe `compressScreenshots` */
|
|
2081
|
+
shotSources?: ReadonlyMap<string, string>;
|
|
1500
2082
|
}
|
|
1501
2083
|
/**
|
|
1502
2084
|
* HTML-Beweisreport im offiziellen CuonzTech-Brand (Terminal-Schwarz, Gold,
|
|
@@ -1523,6 +2105,8 @@ interface CoverOptions {
|
|
|
1523
2105
|
issuedAt?: string;
|
|
1524
2106
|
/** Demo-Lauf mit synthetischen Testdaten — muss aufs Deckblatt */
|
|
1525
2107
|
demo?: boolean;
|
|
2108
|
+
/** Gate-Zustand aus dem Orchestrator; ohne Angabe wird er nur aus den Befunden abgeleitet. */
|
|
2109
|
+
gate?: ReportGate;
|
|
1526
2110
|
}
|
|
1527
2111
|
declare function buildCoverHtml(report: LeakReport, options?: CoverOptions): string;
|
|
1528
2112
|
/**
|
|
@@ -1538,8 +2122,46 @@ declare function renderDeluxeCombined(coverHtml: string, evidenceHtmlPath: strin
|
|
|
1538
2122
|
declare function renderDeluxePdf(coverHtml: string, evidenceHtmlPath: string, outPath: string): Promise<string>;
|
|
1539
2123
|
|
|
1540
2124
|
/**
|
|
1541
|
-
*
|
|
2125
|
+
* Lizenzstatus für die lizenzpflichtigen Funktionen (PDF-Report, Kundenreport, Fix-Commit/PR).
|
|
2126
|
+
* Scan und Konsolen-Gate sind lizenzfrei — nur `invalid` beendet den Lauf (Exit 2).
|
|
2127
|
+
* `unreachable` (Kunden-Key, Lizenzserver weg, kein Grant im Cache) ist ausdrücklich KEIN Fehler:
|
|
2128
|
+
* ein frischer CI-Runner ohne Netz zum Lizenzserver darf das Gate nicht kippen.
|
|
2129
|
+
*/
|
|
2130
|
+
type Entitlement = {
|
|
2131
|
+
status: "licensed";
|
|
2132
|
+
kind: "pilot" | "customer-key";
|
|
2133
|
+
summary: string;
|
|
2134
|
+
} | {
|
|
2135
|
+
status: "none";
|
|
2136
|
+
} | {
|
|
2137
|
+
status: "unreachable";
|
|
2138
|
+
detail: string;
|
|
2139
|
+
} | {
|
|
2140
|
+
status: "invalid";
|
|
2141
|
+
messages: string[];
|
|
2142
|
+
};
|
|
2143
|
+
interface EntitlementInput {
|
|
2144
|
+
/** Wert von `--license` (Vorrang vor Env CPCG_LICENSE) */
|
|
2145
|
+
license?: string;
|
|
2146
|
+
/** Default: process.env */
|
|
2147
|
+
env?: NodeJS.ProcessEnv;
|
|
2148
|
+
/** Test-Stubs */
|
|
2149
|
+
fetchImpl?: typeof fetch;
|
|
2150
|
+
publicKey?: string;
|
|
2151
|
+
}
|
|
2152
|
+
declare const LICENSE_CONTACT = "support@cuonztech.ch bzw. cuonztech.ch/privacy-chaos-gate";
|
|
2153
|
+
declare function resolveEntitlement(input?: EntitlementInput): Promise<Entitlement>;
|
|
2154
|
+
|
|
2155
|
+
/**
|
|
2156
|
+
* Loopback-Ziele (Entwicklung, Fixture-Tests) sind lizenzfrei. Nur der Hostname entscheidet,
|
|
2157
|
+
* nie ein Substring der URL (`https://evil.example/?localhost`, `localhost.evil.example`).
|
|
2158
|
+
*/
|
|
2159
|
+
declare function isLoopbackTarget(url: string): boolean;
|
|
2160
|
+
|
|
2161
|
+
/**
|
|
2162
|
+
* Programmatic convenience function to run CPCG.
|
|
2163
|
+
* Akzeptiert CLI-artige Optionen oder eine (teilweise) Konfiguration; Defaults werden ergänzt.
|
|
1542
2164
|
*/
|
|
1543
|
-
declare function runGate(optionsOrConfig: CliRawOptions |
|
|
2165
|
+
declare function runGate(optionsOrConfig: CliRawOptions | GateConfigInput): Promise<GateExecutionResult>;
|
|
1544
2166
|
|
|
1545
|
-
export {
|
|
2167
|
+
export { type BannerIssue, CORE_SCENARIOS, ChaosScanner, type ChaosScannerInterface, type ChaosScenario, ChaosScenarioSchema, type CliRawOptions, type CodeSolution, type CoverOptions, ENV_FILE_KEYS_HELP, EXIT, type Entitlement, type EntitlementInput, type EvidenceHtmlOptions, type EvidenceMarkdownOptions, type EvidenceRecord, EvidenceRecordSchema, type EvidenceStatus, EvidenceStatusSchema, type FilePatch, FilePatchSchema, type GateAssessment, type GateConfig, type GateConfigInput, GateConfigSchema, type GateExecutionResult, type GateState, type IgnoredFinding, JurisdictionCodeSchema, LICENSE_CONTACT, type LeakReport, LeakReportSchema, PrivacyChaosGate, type PullRequestResult, PullRequestResultSchema, RemediationEngine, type RemediationEngineInterface, type RemediationResult, RemediationResultSchema, type ReportFacts, type ReportGate, type RequestEvent, RequestEventSchema, type ReviewVerdict, ReviewVerdictSchema, type SamplingInfo, type StorageSnapshot, StorageSnapshotSchema, type TrackerCategory, TrackerCategorySchema, type TrackerViolation, TrackerViolationSchema, assessReport, buildCoverHtml, buildEvidenceHtml, buildEvidenceMarkdown, checkTargetReachable, codeSolutionsFor, deriveReportFacts, evidenceLabelOf, findingsCountText, gateNotesOf, groupFindings, isEnvKeyAllowedFromFile, isLoopbackTarget, licenseSkipText, loadProjectEnv, parseGateConfig, problemsTextOf, renderDeluxeCombined, renderDeluxePdf, reproductionText, requestedLicensedFeatures, resolveEntitlement, resolveGateConfig, resolveReportGate, runGate, statusLabelOf, uncheckableReasons };
|