@riddledc/riddle-proof 0.7.89 → 0.7.90
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/README.md +23 -0
- package/dist/{chunk-CEBHV23V.js → chunk-4FMBHM4E.js} +484 -2
- package/dist/cli.cjs +515 -2
- package/dist/cli.js +32 -1
- package/dist/index.cjs +484 -2
- package/dist/index.js +1 -1
- package/dist/profile.cjs +484 -2
- package/dist/profile.d.cts +9 -1
- package/dist/profile.d.ts +9 -1
- package/dist/profile.js +1 -1
- package/dist/proof-run-core.d.cts +1 -1
- package/dist/proof-run-core.d.ts +1 -1
- package/dist/proof-run-engine.d.cts +3 -3
- package/dist/proof-run-engine.d.ts +3 -3
- package/package.json +1 -1
package/dist/profile.cjs
CHANGED
|
@@ -70,6 +70,8 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
|
|
|
70
70
|
"frame_no_horizontal_overflow",
|
|
71
71
|
"text_visible",
|
|
72
72
|
"text_absent",
|
|
73
|
+
"link_status",
|
|
74
|
+
"artifact_link_status",
|
|
73
75
|
"route_inventory",
|
|
74
76
|
"no_horizontal_overflow",
|
|
75
77
|
"no_mobile_horizontal_overflow",
|
|
@@ -734,6 +736,29 @@ function normalizeStringList(value, label) {
|
|
|
734
736
|
if (!values.length) throw new Error(`${label} must contain non-empty strings.`);
|
|
735
737
|
return values;
|
|
736
738
|
}
|
|
739
|
+
function normalizeHttpStatus(value, label) {
|
|
740
|
+
if (value === void 0) return void 0;
|
|
741
|
+
const status = numberValue(value);
|
|
742
|
+
if (status === void 0 || !Number.isInteger(status) || status < 100 || status > 599) {
|
|
743
|
+
throw new Error(`${label} must be an HTTP status code.`);
|
|
744
|
+
}
|
|
745
|
+
return status;
|
|
746
|
+
}
|
|
747
|
+
function normalizeHttpStatuses(value, label) {
|
|
748
|
+
if (value === void 0) return void 0;
|
|
749
|
+
if (!Array.isArray(value)) throw new Error(`${label} must be an array.`);
|
|
750
|
+
if (!value.length) throw new Error(`${label} must not be empty.`);
|
|
751
|
+
const statuses = value.map((item, index) => normalizeHttpStatus(item, `${label}[${index}]`));
|
|
752
|
+
return Array.from(new Set(statuses));
|
|
753
|
+
}
|
|
754
|
+
function normalizePositiveInteger(value, label, max) {
|
|
755
|
+
if (value === void 0) return void 0;
|
|
756
|
+
const number = numberValue(value);
|
|
757
|
+
if (number === void 0 || !Number.isInteger(number) || number < 1 || max !== void 0 && number > max) {
|
|
758
|
+
throw new Error(`${label} must be an integer from 1 to ${max ?? "unbounded"}.`);
|
|
759
|
+
}
|
|
760
|
+
return number;
|
|
761
|
+
}
|
|
737
762
|
function validateRegexPatterns(patterns, label) {
|
|
738
763
|
for (const pattern of patterns || []) {
|
|
739
764
|
try {
|
|
@@ -777,7 +802,8 @@ function normalizeCheck(input, index) {
|
|
|
777
802
|
if (type === "url_search_param_equals" && expectedValue === void 0) {
|
|
778
803
|
throw new Error(`checks[${index}] url_search_param_equals requires expected_value.`);
|
|
779
804
|
}
|
|
780
|
-
|
|
805
|
+
const minCount = numberValue(input.min_count) ?? numberValue(input.minCount);
|
|
806
|
+
if (type === "selector_count_at_least" && minCount === void 0) {
|
|
781
807
|
throw new Error(`checks[${index}] selector_count_at_least requires min_count.`);
|
|
782
808
|
}
|
|
783
809
|
const expectedCount = numberValue(input.expected_count) ?? numberValue(input.expectedCount) ?? numberValue(input.count);
|
|
@@ -793,6 +819,21 @@ function normalizeCheck(input, index) {
|
|
|
793
819
|
if (type === "route_inventory" && !expectedRoutes?.length) {
|
|
794
820
|
throw new Error(`checks[${index}] route_inventory requires expected_routes.`);
|
|
795
821
|
}
|
|
822
|
+
const isLinkStatusCheck = type === "link_status" || type === "artifact_link_status";
|
|
823
|
+
const expectedStatus = isLinkStatusCheck ? normalizeHttpStatus(input.expected_status ?? input.expectedStatus ?? input.status, `checks[${index}] expected_status`) : void 0;
|
|
824
|
+
const allowedStatuses = isLinkStatusCheck ? normalizeHttpStatuses(
|
|
825
|
+
input.allowed_statuses ?? input.allowedStatuses ?? input.expected_statuses ?? input.expectedStatuses,
|
|
826
|
+
`checks[${index}] allowed_statuses`
|
|
827
|
+
) : void 0;
|
|
828
|
+
const maxLinks = isLinkStatusCheck ? normalizePositiveInteger(input.max_links ?? input.maxLinks ?? input.limit, `checks[${index}] max_links`, 500) : void 0;
|
|
829
|
+
if (isLinkStatusCheck) {
|
|
830
|
+
if (minCount !== void 0 && (!Number.isInteger(minCount) || minCount < 0)) {
|
|
831
|
+
throw new Error(`checks[${index}] ${type} min_count must be a non-negative integer.`);
|
|
832
|
+
}
|
|
833
|
+
if (expectedCount !== void 0 && (!Number.isInteger(expectedCount) || expectedCount < 0)) {
|
|
834
|
+
throw new Error(`checks[${index}] ${type} expected_count must be a non-negative integer.`);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
796
837
|
return {
|
|
797
838
|
type,
|
|
798
839
|
label: stringValue(input.label),
|
|
@@ -818,8 +859,15 @@ function normalizeCheck(input, index) {
|
|
|
818
859
|
allowed_console_patterns: normalizeStringList(input.allowed_console_patterns ?? input.allowedConsolePatterns ?? input.allow_console_patterns ?? input.allowConsolePatterns, `checks[${index}] allowed_console_patterns`),
|
|
819
860
|
allowed_page_error_texts: normalizeStringList(input.allowed_page_error_texts ?? input.allowedPageErrorTexts ?? input.allow_page_error_texts ?? input.allowPageErrorTexts, `checks[${index}] allowed_page_error_texts`),
|
|
820
861
|
allowed_page_error_patterns: normalizeStringList(input.allowed_page_error_patterns ?? input.allowedPageErrorPatterns ?? input.allow_page_error_patterns ?? input.allowPageErrorPatterns, `checks[${index}] allowed_page_error_patterns`),
|
|
821
|
-
min_count:
|
|
862
|
+
min_count: minCount,
|
|
822
863
|
expected_count: expectedCount,
|
|
864
|
+
expected_status: expectedStatus,
|
|
865
|
+
allowed_statuses: allowedStatuses,
|
|
866
|
+
max_links: maxLinks,
|
|
867
|
+
same_origin_only: isLinkStatusCheck ? input.same_origin_only === true || input.sameOriginOnly === true : void 0,
|
|
868
|
+
dedupe: isLinkStatusCheck ? input.dedupe === false ? false : true : void 0,
|
|
869
|
+
require_nonzero_bytes: isLinkStatusCheck ? input.require_nonzero_bytes === true || input.requireNonzeroBytes === true : void 0,
|
|
870
|
+
allow_get_fallback: isLinkStatusCheck ? input.allow_get_fallback === false || input.allowGetFallback === false ? false : true : void 0,
|
|
823
871
|
max_overflow_px: numberValue(input.max_overflow_px),
|
|
824
872
|
timeout_ms: numberValue(input.timeout_ms) ?? numberValue(input.timeoutMs),
|
|
825
873
|
run_direct_routes: input.run_direct_routes === false || input.runDirectRoutes === false ? false : true,
|
|
@@ -912,6 +960,97 @@ function checkLabel(check) {
|
|
|
912
960
|
function selectorKey(check) {
|
|
913
961
|
return check.selector || "";
|
|
914
962
|
}
|
|
963
|
+
function linkStatusSelector(check) {
|
|
964
|
+
return check.selector || check.link_selector || "a[href]";
|
|
965
|
+
}
|
|
966
|
+
function linkStatusAllowedStatuses(check) {
|
|
967
|
+
if (check.allowed_statuses?.length) return check.allowed_statuses;
|
|
968
|
+
if (check.expected_status !== void 0) return [check.expected_status];
|
|
969
|
+
return void 0;
|
|
970
|
+
}
|
|
971
|
+
function linkStatusIsAllowed(status, check) {
|
|
972
|
+
if (status === void 0) return false;
|
|
973
|
+
const allowed = linkStatusAllowedStatuses(check);
|
|
974
|
+
return allowed?.length ? allowed.includes(status) : status >= 200 && status < 400;
|
|
975
|
+
}
|
|
976
|
+
function linkStatusResultOk(result, check) {
|
|
977
|
+
const status = numberValue(result.status);
|
|
978
|
+
if (!linkStatusIsAllowed(status, check)) return false;
|
|
979
|
+
if (stringValue(result.error)) return false;
|
|
980
|
+
if (result.ok === false) return false;
|
|
981
|
+
if (check.require_nonzero_bytes) {
|
|
982
|
+
const bytes = numberValue(result.bytes);
|
|
983
|
+
const contentLength = numberValue(result.content_length);
|
|
984
|
+
return bytes !== void 0 && bytes > 0 || contentLength !== void 0 && contentLength > 0;
|
|
985
|
+
}
|
|
986
|
+
return true;
|
|
987
|
+
}
|
|
988
|
+
function linkStatusEvidenceForCheck(viewport, check) {
|
|
989
|
+
const evidence = viewport.link_statuses?.[linkStatusSelector(check)];
|
|
990
|
+
return isRecord(evidence) ? evidence : void 0;
|
|
991
|
+
}
|
|
992
|
+
function summarizeLinkStatusEvidence(viewport, check) {
|
|
993
|
+
const linkEvidence = linkStatusEvidenceForCheck(viewport, check);
|
|
994
|
+
if (!linkEvidence) {
|
|
995
|
+
return {
|
|
996
|
+
viewport: viewport.name,
|
|
997
|
+
selector: linkStatusSelector(check),
|
|
998
|
+
total_count: 0,
|
|
999
|
+
ok_count: 0,
|
|
1000
|
+
failed_count: 1,
|
|
1001
|
+
failures: [{ code: "link_status_evidence_missing" }]
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
const results = Array.isArray(linkEvidence.results) ? linkEvidence.results.filter(isRecord) : [];
|
|
1005
|
+
const totalCount = numberValue(linkEvidence.total_count) ?? results.length;
|
|
1006
|
+
const okCount = results.filter((result) => linkStatusResultOk(result, check)).length;
|
|
1007
|
+
const failures = results.filter((result) => !linkStatusResultOk(result, check)).map((result) => ({
|
|
1008
|
+
code: "link_status_failed",
|
|
1009
|
+
url: stringValue(result.url) ?? null,
|
|
1010
|
+
status: numberValue(result.status) ?? null,
|
|
1011
|
+
method: stringValue(result.method) ?? null,
|
|
1012
|
+
error: stringValue(result.error) ?? null,
|
|
1013
|
+
bytes: numberValue(result.bytes) ?? numberValue(result.content_length) ?? null
|
|
1014
|
+
}));
|
|
1015
|
+
if (stringValue(linkEvidence.error)) {
|
|
1016
|
+
failures.push({ code: "link_status_capture_failed", error: stringValue(linkEvidence.error) ?? "" });
|
|
1017
|
+
}
|
|
1018
|
+
const recordedFailedCount = numberValue(linkEvidence.failed_count) ?? 0;
|
|
1019
|
+
if (!failures.length && recordedFailedCount > 0) {
|
|
1020
|
+
const recordedFailures = Array.isArray(linkEvidence.failures) ? linkEvidence.failures.slice(0, 20) : [];
|
|
1021
|
+
failures.push({
|
|
1022
|
+
code: "link_status_recorded_failures",
|
|
1023
|
+
failed_count: recordedFailedCount,
|
|
1024
|
+
failures: toJsonValue(recordedFailures)
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
if (linkEvidence.truncated === true) {
|
|
1028
|
+
failures.push({
|
|
1029
|
+
code: "link_status_probe_truncated",
|
|
1030
|
+
discovered_count: numberValue(linkEvidence.discovered_count) ?? totalCount,
|
|
1031
|
+
max_links: numberValue(linkEvidence.max_links) ?? check.max_links ?? 100
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
if (check.expected_count !== void 0 && totalCount !== check.expected_count) {
|
|
1035
|
+
failures.push({ code: "link_status_count_mismatch", expected: check.expected_count, actual: totalCount });
|
|
1036
|
+
}
|
|
1037
|
+
if (check.min_count !== void 0 && totalCount < check.min_count) {
|
|
1038
|
+
failures.push({ code: "link_status_count_below_minimum", min_count: check.min_count, actual: totalCount });
|
|
1039
|
+
}
|
|
1040
|
+
const statusCounts = isRecord(linkEvidence.status_counts) ? linkEvidence.status_counts : {};
|
|
1041
|
+
return {
|
|
1042
|
+
viewport: viewport.name,
|
|
1043
|
+
selector: linkStatusSelector(check),
|
|
1044
|
+
total_count: totalCount,
|
|
1045
|
+
discovered_count: numberValue(linkEvidence.discovered_count) ?? totalCount,
|
|
1046
|
+
ok_count: numberValue(linkEvidence.ok_count) ?? okCount,
|
|
1047
|
+
failed_count: failures.length,
|
|
1048
|
+
truncated: linkEvidence.truncated === true,
|
|
1049
|
+
max_links: numberValue(linkEvidence.max_links) ?? check.max_links ?? 100,
|
|
1050
|
+
status_counts: statusCounts,
|
|
1051
|
+
failures: failures.slice(0, 20)
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
915
1054
|
function textKey(check) {
|
|
916
1055
|
return check.pattern ? `pattern:${check.pattern}/${check.flags || ""}` : `text:${check.text || ""}`;
|
|
917
1056
|
}
|
|
@@ -1391,6 +1530,26 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
1391
1530
|
message: failed ? `Text assertion failed in ${failed} viewport(s).` : void 0
|
|
1392
1531
|
};
|
|
1393
1532
|
}
|
|
1533
|
+
if (check.type === "link_status" || check.type === "artifact_link_status") {
|
|
1534
|
+
const selector = linkStatusSelector(check);
|
|
1535
|
+
const summaries = viewports.map((viewport) => summarizeLinkStatusEvidence(viewport, check));
|
|
1536
|
+
const failed = summaries.filter((summary) => (numberValue(summary.failed_count) ?? 0) > 0);
|
|
1537
|
+
return {
|
|
1538
|
+
type: check.type,
|
|
1539
|
+
label: checkLabel(check),
|
|
1540
|
+
status: failed.length ? "failed" : "passed",
|
|
1541
|
+
evidence: {
|
|
1542
|
+
selector,
|
|
1543
|
+
expected_count: check.expected_count ?? null,
|
|
1544
|
+
min_count: check.min_count ?? null,
|
|
1545
|
+
allowed_statuses: linkStatusAllowedStatuses(check) || ["2xx", "3xx"],
|
|
1546
|
+
require_nonzero_bytes: check.require_nonzero_bytes === true,
|
|
1547
|
+
viewports: summaries.map((summary) => toJsonValue(summary)),
|
|
1548
|
+
failures: failed.flatMap((summary) => Array.isArray(summary.failures) ? summary.failures.map((failure) => toJsonValue({ viewport: stringValue(summary.viewport) ?? null, failure })) : [])
|
|
1549
|
+
},
|
|
1550
|
+
message: failed.length ? `Link status failed in ${failed.length} viewport(s).` : void 0
|
|
1551
|
+
};
|
|
1552
|
+
}
|
|
1394
1553
|
if (check.type === "route_inventory") {
|
|
1395
1554
|
const inventories = viewports.map((viewport) => ({ viewport: viewport.name, inventory: viewport.route_inventory })).filter((item) => isRecord(item.inventory));
|
|
1396
1555
|
if (!inventories.length) {
|
|
@@ -1973,6 +2132,98 @@ function textOrderMatch(texts, expectedTexts) {
|
|
|
1973
2132
|
}
|
|
1974
2133
|
return { matched: true, positions };
|
|
1975
2134
|
}
|
|
2135
|
+
function linkStatusSelector(check) {
|
|
2136
|
+
return check.selector || check.link_selector || "a[href]";
|
|
2137
|
+
}
|
|
2138
|
+
function linkStatusAllowedStatuses(check) {
|
|
2139
|
+
if (Array.isArray(check.allowed_statuses) && check.allowed_statuses.length) return check.allowed_statuses;
|
|
2140
|
+
if (typeof check.expected_status === "number" && Number.isFinite(check.expected_status)) return [check.expected_status];
|
|
2141
|
+
return undefined;
|
|
2142
|
+
}
|
|
2143
|
+
function linkStatusIsAllowed(status, check) {
|
|
2144
|
+
if (typeof status !== "number" || !Number.isFinite(status)) return false;
|
|
2145
|
+
const allowed = linkStatusAllowedStatuses(check);
|
|
2146
|
+
return Array.isArray(allowed) && allowed.length ? allowed.includes(status) : status >= 200 && status < 400;
|
|
2147
|
+
}
|
|
2148
|
+
function linkStatusResultOk(result, check) {
|
|
2149
|
+
if (!result || typeof result !== "object" || Array.isArray(result)) return false;
|
|
2150
|
+
if (!linkStatusIsAllowed(result.status, check)) return false;
|
|
2151
|
+
if (typeof result.error === "string" && result.error.trim()) return false;
|
|
2152
|
+
if (result.ok === false) return false;
|
|
2153
|
+
if (check.require_nonzero_bytes === true) {
|
|
2154
|
+
const bytes = typeof result.bytes === "number" && Number.isFinite(result.bytes) ? result.bytes : undefined;
|
|
2155
|
+
const contentLength = typeof result.content_length === "number" && Number.isFinite(result.content_length) ? result.content_length : undefined;
|
|
2156
|
+
return (bytes !== undefined && bytes > 0) || (contentLength !== undefined && contentLength > 0);
|
|
2157
|
+
}
|
|
2158
|
+
return true;
|
|
2159
|
+
}
|
|
2160
|
+
function summarizeLinkStatusEvidence(viewport, check) {
|
|
2161
|
+
const selector = linkStatusSelector(check);
|
|
2162
|
+
const linkEvidence = viewport && viewport.link_statuses && viewport.link_statuses[selector];
|
|
2163
|
+
if (!linkEvidence || typeof linkEvidence !== "object" || Array.isArray(linkEvidence)) {
|
|
2164
|
+
return {
|
|
2165
|
+
viewport: viewport && viewport.name,
|
|
2166
|
+
selector,
|
|
2167
|
+
total_count: 0,
|
|
2168
|
+
ok_count: 0,
|
|
2169
|
+
failed_count: 1,
|
|
2170
|
+
failures: [{ code: "link_status_evidence_missing" }],
|
|
2171
|
+
};
|
|
2172
|
+
}
|
|
2173
|
+
const results = Array.isArray(linkEvidence.results) ? linkEvidence.results.filter((result) => result && typeof result === "object" && !Array.isArray(result)) : [];
|
|
2174
|
+
const totalCount = typeof linkEvidence.total_count === "number" && Number.isFinite(linkEvidence.total_count) ? linkEvidence.total_count : results.length;
|
|
2175
|
+
const okCount = results.filter((result) => linkStatusResultOk(result, check)).length;
|
|
2176
|
+
const failures = results
|
|
2177
|
+
.filter((result) => !linkStatusResultOk(result, check))
|
|
2178
|
+
.map((result) => ({
|
|
2179
|
+
code: "link_status_failed",
|
|
2180
|
+
url: typeof result.url === "string" ? result.url : null,
|
|
2181
|
+
status: typeof result.status === "number" && Number.isFinite(result.status) ? result.status : null,
|
|
2182
|
+
method: typeof result.method === "string" ? result.method : null,
|
|
2183
|
+
error: typeof result.error === "string" ? result.error : null,
|
|
2184
|
+
bytes: typeof result.bytes === "number" && Number.isFinite(result.bytes)
|
|
2185
|
+
? result.bytes
|
|
2186
|
+
: typeof result.content_length === "number" && Number.isFinite(result.content_length)
|
|
2187
|
+
? result.content_length
|
|
2188
|
+
: null,
|
|
2189
|
+
}));
|
|
2190
|
+
if (typeof linkEvidence.error === "string" && linkEvidence.error.trim()) {
|
|
2191
|
+
failures.push({ code: "link_status_capture_failed", error: linkEvidence.error });
|
|
2192
|
+
}
|
|
2193
|
+
const recordedFailedCount = typeof linkEvidence.failed_count === "number" && Number.isFinite(linkEvidence.failed_count) ? linkEvidence.failed_count : 0;
|
|
2194
|
+
if (!failures.length && recordedFailedCount > 0) {
|
|
2195
|
+
failures.push({
|
|
2196
|
+
code: "link_status_recorded_failures",
|
|
2197
|
+
failed_count: recordedFailedCount,
|
|
2198
|
+
failures: Array.isArray(linkEvidence.failures) ? linkEvidence.failures.slice(0, 20) : [],
|
|
2199
|
+
});
|
|
2200
|
+
}
|
|
2201
|
+
if (linkEvidence.truncated === true) {
|
|
2202
|
+
failures.push({
|
|
2203
|
+
code: "link_status_probe_truncated",
|
|
2204
|
+
discovered_count: typeof linkEvidence.discovered_count === "number" ? linkEvidence.discovered_count : totalCount,
|
|
2205
|
+
max_links: typeof linkEvidence.max_links === "number" ? linkEvidence.max_links : check.max_links || 100,
|
|
2206
|
+
});
|
|
2207
|
+
}
|
|
2208
|
+
if (typeof check.expected_count === "number" && Number.isFinite(check.expected_count) && totalCount !== check.expected_count) {
|
|
2209
|
+
failures.push({ code: "link_status_count_mismatch", expected: check.expected_count, actual: totalCount });
|
|
2210
|
+
}
|
|
2211
|
+
if (typeof check.min_count === "number" && Number.isFinite(check.min_count) && totalCount < check.min_count) {
|
|
2212
|
+
failures.push({ code: "link_status_count_below_minimum", min_count: check.min_count, actual: totalCount });
|
|
2213
|
+
}
|
|
2214
|
+
return {
|
|
2215
|
+
viewport: viewport && viewport.name,
|
|
2216
|
+
selector,
|
|
2217
|
+
total_count: totalCount,
|
|
2218
|
+
discovered_count: typeof linkEvidence.discovered_count === "number" ? linkEvidence.discovered_count : totalCount,
|
|
2219
|
+
ok_count: typeof linkEvidence.ok_count === "number" ? linkEvidence.ok_count : okCount,
|
|
2220
|
+
failed_count: failures.length,
|
|
2221
|
+
truncated: linkEvidence.truncated === true,
|
|
2222
|
+
max_links: typeof linkEvidence.max_links === "number" ? linkEvidence.max_links : check.max_links || 100,
|
|
2223
|
+
status_counts: linkEvidence.status_counts && typeof linkEvidence.status_counts === "object" && !Array.isArray(linkEvidence.status_counts) ? linkEvidence.status_counts : {},
|
|
2224
|
+
failures: failures.slice(0, 20),
|
|
2225
|
+
};
|
|
2226
|
+
}
|
|
1976
2227
|
function frameEvidenceForSelector(viewport, selector) {
|
|
1977
2228
|
const container = viewport.frames && viewport.frames[selector || ""];
|
|
1978
2229
|
if (!container || typeof container !== "object" || Array.isArray(container)) return [];
|
|
@@ -2626,6 +2877,29 @@ function assessProfile(profile, evidence) {
|
|
|
2626
2877
|
});
|
|
2627
2878
|
continue;
|
|
2628
2879
|
}
|
|
2880
|
+
if (check.type === "link_status" || check.type === "artifact_link_status") {
|
|
2881
|
+
const selector = linkStatusSelector(check);
|
|
2882
|
+
const summaries = checkViewports.map((viewport) => summarizeLinkStatusEvidence(viewport, check));
|
|
2883
|
+
const failed = summaries.filter((summary) => summary.failed_count > 0);
|
|
2884
|
+
checks.push({
|
|
2885
|
+
type: check.type,
|
|
2886
|
+
label: check.label || check.type,
|
|
2887
|
+
status: failed.length ? "failed" : "passed",
|
|
2888
|
+
evidence: {
|
|
2889
|
+
selector,
|
|
2890
|
+
expected_count: check.expected_count ?? null,
|
|
2891
|
+
min_count: check.min_count ?? null,
|
|
2892
|
+
allowed_statuses: linkStatusAllowedStatuses(check) || ["2xx", "3xx"],
|
|
2893
|
+
require_nonzero_bytes: check.require_nonzero_bytes === true,
|
|
2894
|
+
viewports: summaries,
|
|
2895
|
+
failures: failed.flatMap((summary) => Array.isArray(summary.failures)
|
|
2896
|
+
? summary.failures.map((failure) => ({ viewport: summary.viewport || null, failure }))
|
|
2897
|
+
: []),
|
|
2898
|
+
},
|
|
2899
|
+
message: failed.length ? "Link status failed in " + failed.length + " viewport(s)." : undefined,
|
|
2900
|
+
});
|
|
2901
|
+
continue;
|
|
2902
|
+
}
|
|
2629
2903
|
if (check.type === "route_inventory") {
|
|
2630
2904
|
const inventories = checkViewports
|
|
2631
2905
|
.map((viewport) => ({ viewport: viewport.name, inventory: viewport.route_inventory }))
|
|
@@ -3684,6 +3958,196 @@ async function selectorTextSequence(selector) {
|
|
|
3684
3958
|
};
|
|
3685
3959
|
}).catch((error) => ({ count: 0, visible_count: 0, texts: [], visible_texts: [], error: String(error && error.message ? error.message : error).slice(0, 500) }));
|
|
3686
3960
|
}
|
|
3961
|
+
function linkProbeMaxLinks(check) {
|
|
3962
|
+
const value = Number(check.max_links || check.maxLinks || check.limit || 100);
|
|
3963
|
+
return Number.isInteger(value) && value > 0 ? Math.min(value, 500) : 100;
|
|
3964
|
+
}
|
|
3965
|
+
function linkProbeDedupe(check) {
|
|
3966
|
+
return check.dedupe !== false;
|
|
3967
|
+
}
|
|
3968
|
+
function linkProbeSameOriginOnly(check) {
|
|
3969
|
+
return check.same_origin_only === true;
|
|
3970
|
+
}
|
|
3971
|
+
async function collectLinkCandidates(selector) {
|
|
3972
|
+
return page.locator(selector).evaluateAll((elements) => {
|
|
3973
|
+
const compact = (value, limit) => String(value || "").replace(/\s+/g, " ").trim().slice(0, limit || 160);
|
|
3974
|
+
return elements.map((element, index) => {
|
|
3975
|
+
const tag = element && element.tagName ? element.tagName.toLowerCase() : "element";
|
|
3976
|
+
const href = element && typeof element.href === "string" ? element.href : "";
|
|
3977
|
+
const src = element && typeof element.src === "string" ? element.src : "";
|
|
3978
|
+
const currentSrc = element && typeof element.currentSrc === "string" ? element.currentSrc : "";
|
|
3979
|
+
const attrHref = element && typeof element.getAttribute === "function" ? element.getAttribute("href") || "" : "";
|
|
3980
|
+
const attrSrc = element && typeof element.getAttribute === "function" ? element.getAttribute("src") || "" : "";
|
|
3981
|
+
const attrPoster = element && typeof element.getAttribute === "function" ? element.getAttribute("poster") || "" : "";
|
|
3982
|
+
const raw = href || currentSrc || src || attrHref || attrSrc || attrPoster;
|
|
3983
|
+
if (!raw) return null;
|
|
3984
|
+
let url = "";
|
|
3985
|
+
try {
|
|
3986
|
+
url = new URL(raw, location.href).href;
|
|
3987
|
+
} catch {}
|
|
3988
|
+
if (!url) return null;
|
|
3989
|
+
return {
|
|
3990
|
+
index,
|
|
3991
|
+
tag,
|
|
3992
|
+
url,
|
|
3993
|
+
raw,
|
|
3994
|
+
text: compact(element.innerText || element.textContent || "", 160),
|
|
3995
|
+
alt: compact(element.getAttribute && element.getAttribute("alt"), 80),
|
|
3996
|
+
};
|
|
3997
|
+
}).filter(Boolean);
|
|
3998
|
+
}).catch((error) => ({ error: String(error && error.message ? error.message : error).slice(0, 500) }));
|
|
3999
|
+
}
|
|
4000
|
+
function linkProbeAllowed(status, check) {
|
|
4001
|
+
if (typeof status !== "number" || !Number.isFinite(status)) return false;
|
|
4002
|
+
const allowed = Array.isArray(check.allowed_statuses) && check.allowed_statuses.length
|
|
4003
|
+
? check.allowed_statuses
|
|
4004
|
+
: typeof check.expected_status === "number" && Number.isFinite(check.expected_status)
|
|
4005
|
+
? [check.expected_status]
|
|
4006
|
+
: null;
|
|
4007
|
+
return allowed ? allowed.includes(status) : status >= 200 && status < 400;
|
|
4008
|
+
}
|
|
4009
|
+
function linkProbeResponseFields(response, method) {
|
|
4010
|
+
const contentLengthHeader = response.headers && typeof response.headers.get === "function" ? response.headers.get("content-length") : null;
|
|
4011
|
+
const contentLength = contentLengthHeader && /^\d+$/.test(contentLengthHeader) ? Number(contentLengthHeader) : null;
|
|
4012
|
+
return {
|
|
4013
|
+
method,
|
|
4014
|
+
status: response.status,
|
|
4015
|
+
redirected: Boolean(response.redirected),
|
|
4016
|
+
final_url: response.url || null,
|
|
4017
|
+
content_type: response.headers && typeof response.headers.get === "function" ? response.headers.get("content-type") : null,
|
|
4018
|
+
content_length: contentLength,
|
|
4019
|
+
};
|
|
4020
|
+
}
|
|
4021
|
+
async function probeLinkStatus(candidate, check) {
|
|
4022
|
+
const requireNonzeroBytes = check.require_nonzero_bytes === true;
|
|
4023
|
+
const allowGetFallback = check.allow_get_fallback !== false;
|
|
4024
|
+
const result = {
|
|
4025
|
+
url: candidate.url,
|
|
4026
|
+
tag: candidate.tag,
|
|
4027
|
+
text: candidate.text || null,
|
|
4028
|
+
status: null,
|
|
4029
|
+
method: null,
|
|
4030
|
+
ok: false,
|
|
4031
|
+
content_type: null,
|
|
4032
|
+
content_length: null,
|
|
4033
|
+
bytes: null,
|
|
4034
|
+
redirected: false,
|
|
4035
|
+
final_url: null,
|
|
4036
|
+
error: null,
|
|
4037
|
+
};
|
|
4038
|
+
const applyResponse = async (response, method, readBytes) => {
|
|
4039
|
+
Object.assign(result, linkProbeResponseFields(response, method));
|
|
4040
|
+
if (readBytes || requireNonzeroBytes) {
|
|
4041
|
+
try {
|
|
4042
|
+
const buffer = await response.arrayBuffer();
|
|
4043
|
+
result.bytes = buffer.byteLength;
|
|
4044
|
+
} catch (error) {
|
|
4045
|
+
result.error = String(error && error.message ? error.message : error).slice(0, 500);
|
|
4046
|
+
}
|
|
4047
|
+
}
|
|
4048
|
+
result.ok = linkProbeAllowed(result.status, check)
|
|
4049
|
+
&& (!requireNonzeroBytes || (typeof result.bytes === "number" ? result.bytes > 0 : typeof result.content_length === "number" && result.content_length > 0))
|
|
4050
|
+
&& !result.error;
|
|
4051
|
+
};
|
|
4052
|
+
try {
|
|
4053
|
+
const response = await fetch(candidate.url, { method: "HEAD", redirect: "follow", cache: "no-store" });
|
|
4054
|
+
await applyResponse(response, "HEAD", false);
|
|
4055
|
+
if (result.ok || !allowGetFallback) return result;
|
|
4056
|
+
} catch (error) {
|
|
4057
|
+
result.error = String(error && error.message ? error.message : error).slice(0, 500);
|
|
4058
|
+
if (!allowGetFallback) return result;
|
|
4059
|
+
}
|
|
4060
|
+
try {
|
|
4061
|
+
result.error = null;
|
|
4062
|
+
const response = await fetch(candidate.url, {
|
|
4063
|
+
method: "GET",
|
|
4064
|
+
redirect: "follow",
|
|
4065
|
+
cache: "no-store",
|
|
4066
|
+
headers: { Range: "bytes=0-0" },
|
|
4067
|
+
});
|
|
4068
|
+
await applyResponse(response, "GET", requireNonzeroBytes);
|
|
4069
|
+
return result;
|
|
4070
|
+
} catch (error) {
|
|
4071
|
+
result.error = String(error && error.message ? error.message : error).slice(0, 500);
|
|
4072
|
+
result.ok = false;
|
|
4073
|
+
return result;
|
|
4074
|
+
}
|
|
4075
|
+
}
|
|
4076
|
+
async function collectLinkStatus(check) {
|
|
4077
|
+
const selector = linkStatusSelector(check);
|
|
4078
|
+
const candidateResult = await collectLinkCandidates(selector);
|
|
4079
|
+
if (candidateResult && candidateResult.error) {
|
|
4080
|
+
return {
|
|
4081
|
+
version: "riddle-proof.link-status.v1",
|
|
4082
|
+
selector,
|
|
4083
|
+
total_count: 0,
|
|
4084
|
+
discovered_count: 0,
|
|
4085
|
+
ok_count: 0,
|
|
4086
|
+
failed_count: 1,
|
|
4087
|
+
failures: [{ code: "link_status_capture_failed", error: candidateResult.error }],
|
|
4088
|
+
results: [],
|
|
4089
|
+
status_counts: {},
|
|
4090
|
+
error: candidateResult.error,
|
|
4091
|
+
};
|
|
4092
|
+
}
|
|
4093
|
+
const baseUrl = page.url() || targetUrl;
|
|
4094
|
+
let candidates = Array.isArray(candidateResult) ? candidateResult : [];
|
|
4095
|
+
if (linkProbeSameOriginOnly(check)) {
|
|
4096
|
+
const origin = new URL(baseUrl).origin;
|
|
4097
|
+
candidates = candidates.filter((candidate) => {
|
|
4098
|
+
try { return new URL(candidate.url).origin === origin; } catch { return false; }
|
|
4099
|
+
});
|
|
4100
|
+
}
|
|
4101
|
+
const discoveredCount = candidates.length;
|
|
4102
|
+
if (linkProbeDedupe(check)) {
|
|
4103
|
+
const seen = new Set();
|
|
4104
|
+
candidates = candidates.filter((candidate) => {
|
|
4105
|
+
if (seen.has(candidate.url)) return false;
|
|
4106
|
+
seen.add(candidate.url);
|
|
4107
|
+
return true;
|
|
4108
|
+
});
|
|
4109
|
+
}
|
|
4110
|
+
const maxLinks = linkProbeMaxLinks(check);
|
|
4111
|
+
const selected = candidates.slice(0, maxLinks);
|
|
4112
|
+
const results = [];
|
|
4113
|
+
for (const candidate of selected) {
|
|
4114
|
+
results.push(await probeLinkStatus(candidate, check));
|
|
4115
|
+
}
|
|
4116
|
+
const failures = results.filter((result) => !result.ok).map((result) => ({
|
|
4117
|
+
code: "link_status_failed",
|
|
4118
|
+
url: result.url,
|
|
4119
|
+
status: result.status,
|
|
4120
|
+
method: result.method,
|
|
4121
|
+
error: result.error,
|
|
4122
|
+
bytes: result.bytes == null ? result.content_length : result.bytes,
|
|
4123
|
+
}));
|
|
4124
|
+
const statusCounts = {};
|
|
4125
|
+
for (const result of results) {
|
|
4126
|
+
const key = result.status == null ? "error" : String(result.status);
|
|
4127
|
+
statusCounts[key] = (statusCounts[key] || 0) + 1;
|
|
4128
|
+
}
|
|
4129
|
+
return {
|
|
4130
|
+
version: "riddle-proof.link-status.v1",
|
|
4131
|
+
selector,
|
|
4132
|
+
max_links: maxLinks,
|
|
4133
|
+
same_origin_only: linkProbeSameOriginOnly(check),
|
|
4134
|
+
dedupe: linkProbeDedupe(check),
|
|
4135
|
+
require_nonzero_bytes: check.require_nonzero_bytes === true,
|
|
4136
|
+
allowed_statuses: Array.isArray(check.allowed_statuses) && check.allowed_statuses.length
|
|
4137
|
+
? check.allowed_statuses
|
|
4138
|
+
: typeof check.expected_status === "number"
|
|
4139
|
+
? [check.expected_status]
|
|
4140
|
+
: ["2xx", "3xx"],
|
|
4141
|
+
discovered_count: discoveredCount,
|
|
4142
|
+
total_count: selected.length,
|
|
4143
|
+
truncated: candidates.length > selected.length,
|
|
4144
|
+
ok_count: results.filter((result) => result.ok).length,
|
|
4145
|
+
failed_count: failures.length,
|
|
4146
|
+
status_counts: statusCounts,
|
|
4147
|
+
failures: failures.slice(0, 20),
|
|
4148
|
+
results,
|
|
4149
|
+
};
|
|
4150
|
+
}
|
|
3687
4151
|
async function frameEvidence(selector) {
|
|
3688
4152
|
const result = { selector, count: 0, frame_count: 0, frames: [], errors: [] };
|
|
3689
4153
|
let handles = [];
|
|
@@ -4203,6 +4667,7 @@ async function captureViewport(viewport) {
|
|
|
4203
4667
|
const frames = {};
|
|
4204
4668
|
const text_sequences = {};
|
|
4205
4669
|
const text_matches = {};
|
|
4670
|
+
const link_statuses = {};
|
|
4206
4671
|
for (const check of profile.checks || []) {
|
|
4207
4672
|
if (
|
|
4208
4673
|
(
|
|
@@ -4227,6 +4692,10 @@ async function captureViewport(viewport) {
|
|
|
4227
4692
|
selectors[check.selector] = selectors[check.selector] || await selectorStats(check.selector);
|
|
4228
4693
|
frames[check.selector] = frames[check.selector] || await frameEvidence(check.selector);
|
|
4229
4694
|
}
|
|
4695
|
+
if (check.type === "link_status" || check.type === "artifact_link_status") {
|
|
4696
|
+
const selector = linkStatusSelector(check);
|
|
4697
|
+
link_statuses[selector] = link_statuses[selector] || await collectLinkStatus(check);
|
|
4698
|
+
}
|
|
4230
4699
|
}
|
|
4231
4700
|
const screenshotLabel = profileSlug + "-" + viewport.name;
|
|
4232
4701
|
try {
|
|
@@ -4290,6 +4759,7 @@ async function captureViewport(viewport) {
|
|
|
4290
4759
|
frames,
|
|
4291
4760
|
text_sequences,
|
|
4292
4761
|
text_matches,
|
|
4762
|
+
link_statuses,
|
|
4293
4763
|
route_inventory: routeInventory,
|
|
4294
4764
|
setup_action_results: setupActionResults,
|
|
4295
4765
|
screenshot_label: screenshotLabel,
|
|
@@ -4338,6 +4808,18 @@ function buildProfileEvidence(currentViewports) {
|
|
|
4338
4808
|
),
|
|
4339
4809
|
})),
|
|
4340
4810
|
})),
|
|
4811
|
+
link_status: currentViewports
|
|
4812
|
+
.filter((viewport) => viewport.link_statuses)
|
|
4813
|
+
.map((viewport) => ({
|
|
4814
|
+
viewport: viewport.name,
|
|
4815
|
+
selectors: Object.entries(viewport.link_statuses || {}).map(([selector, statusSet]) => ({
|
|
4816
|
+
selector,
|
|
4817
|
+
total_count: statusSet && statusSet.total_count,
|
|
4818
|
+
ok_count: statusSet && statusSet.ok_count,
|
|
4819
|
+
failed_count: statusSet && statusSet.failed_count,
|
|
4820
|
+
truncated: statusSet && statusSet.truncated === true,
|
|
4821
|
+
})),
|
|
4822
|
+
})),
|
|
4341
4823
|
route_inventory: currentViewports
|
|
4342
4824
|
.filter((viewport) => viewport.route_inventory)
|
|
4343
4825
|
.map((viewport) => ({
|
package/dist/profile.d.cts
CHANGED
|
@@ -4,7 +4,7 @@ declare const RIDDLE_PROOF_PROFILE_VERSION: "riddle-proof.profile.v1";
|
|
|
4
4
|
declare const RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: "riddle-proof.profile-evidence.v1";
|
|
5
5
|
declare const RIDDLE_PROOF_PROFILE_RESULT_VERSION: "riddle-proof.profile-result.v1";
|
|
6
6
|
declare const RIDDLE_PROOF_PROFILE_STATUSES: readonly ["passed", "product_regression", "proof_insufficient", "environment_blocked", "configuration_error", "needs_human_review"];
|
|
7
|
-
declare const RIDDLE_PROOF_PROFILE_CHECK_TYPES: readonly ["route_loaded", "url_search_param_equals", "url_search_param_absent", "selector_visible", "selector_absent", "selector_count_at_least", "selector_count_equals", "selector_count_equal", "selector_count_eq", "selector_text_order", "frame_text_visible", "frame_url_equals", "frame_url_matches", "frame_no_horizontal_overflow", "text_visible", "text_absent", "route_inventory", "no_horizontal_overflow", "no_mobile_horizontal_overflow", "no_fatal_console_errors"];
|
|
7
|
+
declare const RIDDLE_PROOF_PROFILE_CHECK_TYPES: readonly ["route_loaded", "url_search_param_equals", "url_search_param_absent", "selector_visible", "selector_absent", "selector_count_at_least", "selector_count_equals", "selector_count_equal", "selector_count_eq", "selector_text_order", "frame_text_visible", "frame_url_equals", "frame_url_matches", "frame_no_horizontal_overflow", "text_visible", "text_absent", "link_status", "artifact_link_status", "route_inventory", "no_horizontal_overflow", "no_mobile_horizontal_overflow", "no_fatal_console_errors"];
|
|
8
8
|
declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "drag", "press", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "assert_window_value", "assert_window_number", "local_storage", "session_storage", "clear_storage", "clear_console", "dialog_response", "screenshot", "wait", "wait_for_selector", "wait_for_text", "window_call"];
|
|
9
9
|
type RiddleProofProfileStatus = typeof RIDDLE_PROOF_PROFILE_STATUSES[number];
|
|
10
10
|
type RiddleProofProfileCheckType = typeof RIDDLE_PROOF_PROFILE_CHECK_TYPES[number];
|
|
@@ -132,6 +132,13 @@ interface RiddleProofProfileCheck {
|
|
|
132
132
|
allowed_page_error_patterns?: string[];
|
|
133
133
|
min_count?: number;
|
|
134
134
|
expected_count?: number;
|
|
135
|
+
expected_status?: number;
|
|
136
|
+
allowed_statuses?: number[];
|
|
137
|
+
max_links?: number;
|
|
138
|
+
same_origin_only?: boolean;
|
|
139
|
+
dedupe?: boolean;
|
|
140
|
+
require_nonzero_bytes?: boolean;
|
|
141
|
+
allow_get_fallback?: boolean;
|
|
135
142
|
max_overflow_px?: number;
|
|
136
143
|
timeout_ms?: number;
|
|
137
144
|
run_direct_routes?: boolean;
|
|
@@ -196,6 +203,7 @@ interface RiddleProofProfileViewportEvidence {
|
|
|
196
203
|
frames?: Record<string, Record<string, JsonValue>>;
|
|
197
204
|
text_sequences?: Record<string, Record<string, JsonValue>>;
|
|
198
205
|
text_matches?: Record<string, boolean>;
|
|
206
|
+
link_statuses?: Record<string, Record<string, JsonValue>>;
|
|
199
207
|
route_inventory?: Record<string, JsonValue>;
|
|
200
208
|
setup_action_results?: Array<Record<string, JsonValue>>;
|
|
201
209
|
screenshot_label?: string;
|
package/dist/profile.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ declare const RIDDLE_PROOF_PROFILE_VERSION: "riddle-proof.profile.v1";
|
|
|
4
4
|
declare const RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: "riddle-proof.profile-evidence.v1";
|
|
5
5
|
declare const RIDDLE_PROOF_PROFILE_RESULT_VERSION: "riddle-proof.profile-result.v1";
|
|
6
6
|
declare const RIDDLE_PROOF_PROFILE_STATUSES: readonly ["passed", "product_regression", "proof_insufficient", "environment_blocked", "configuration_error", "needs_human_review"];
|
|
7
|
-
declare const RIDDLE_PROOF_PROFILE_CHECK_TYPES: readonly ["route_loaded", "url_search_param_equals", "url_search_param_absent", "selector_visible", "selector_absent", "selector_count_at_least", "selector_count_equals", "selector_count_equal", "selector_count_eq", "selector_text_order", "frame_text_visible", "frame_url_equals", "frame_url_matches", "frame_no_horizontal_overflow", "text_visible", "text_absent", "route_inventory", "no_horizontal_overflow", "no_mobile_horizontal_overflow", "no_fatal_console_errors"];
|
|
7
|
+
declare const RIDDLE_PROOF_PROFILE_CHECK_TYPES: readonly ["route_loaded", "url_search_param_equals", "url_search_param_absent", "selector_visible", "selector_absent", "selector_count_at_least", "selector_count_equals", "selector_count_equal", "selector_count_eq", "selector_text_order", "frame_text_visible", "frame_url_equals", "frame_url_matches", "frame_no_horizontal_overflow", "text_visible", "text_absent", "link_status", "artifact_link_status", "route_inventory", "no_horizontal_overflow", "no_mobile_horizontal_overflow", "no_fatal_console_errors"];
|
|
8
8
|
declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "drag", "press", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "assert_window_value", "assert_window_number", "local_storage", "session_storage", "clear_storage", "clear_console", "dialog_response", "screenshot", "wait", "wait_for_selector", "wait_for_text", "window_call"];
|
|
9
9
|
type RiddleProofProfileStatus = typeof RIDDLE_PROOF_PROFILE_STATUSES[number];
|
|
10
10
|
type RiddleProofProfileCheckType = typeof RIDDLE_PROOF_PROFILE_CHECK_TYPES[number];
|
|
@@ -132,6 +132,13 @@ interface RiddleProofProfileCheck {
|
|
|
132
132
|
allowed_page_error_patterns?: string[];
|
|
133
133
|
min_count?: number;
|
|
134
134
|
expected_count?: number;
|
|
135
|
+
expected_status?: number;
|
|
136
|
+
allowed_statuses?: number[];
|
|
137
|
+
max_links?: number;
|
|
138
|
+
same_origin_only?: boolean;
|
|
139
|
+
dedupe?: boolean;
|
|
140
|
+
require_nonzero_bytes?: boolean;
|
|
141
|
+
allow_get_fallback?: boolean;
|
|
135
142
|
max_overflow_px?: number;
|
|
136
143
|
timeout_ms?: number;
|
|
137
144
|
run_direct_routes?: boolean;
|
|
@@ -196,6 +203,7 @@ interface RiddleProofProfileViewportEvidence {
|
|
|
196
203
|
frames?: Record<string, Record<string, JsonValue>>;
|
|
197
204
|
text_sequences?: Record<string, Record<string, JsonValue>>;
|
|
198
205
|
text_matches?: Record<string, boolean>;
|
|
206
|
+
link_statuses?: Record<string, Record<string, JsonValue>>;
|
|
199
207
|
route_inventory?: Record<string, JsonValue>;
|
|
200
208
|
setup_action_results?: Array<Record<string, JsonValue>>;
|
|
201
209
|
screenshot_label?: string;
|
package/dist/profile.js
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
resolveRiddleProofProfileTimeoutSec,
|
|
20
20
|
slugifyRiddleProofProfileName,
|
|
21
21
|
summarizeRiddleProofProfileResult
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-4FMBHM4E.js";
|
|
23
23
|
export {
|
|
24
24
|
RIDDLE_PROOF_PROFILE_CHECK_TYPES,
|
|
25
25
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|
|
@@ -120,7 +120,7 @@ declare function buildSetupArgs(params: WorkflowParams, config: ReturnType<typeo
|
|
|
120
120
|
target_image_hash: string;
|
|
121
121
|
viewport_matrix_json: string;
|
|
122
122
|
deterministic_setup_json: string;
|
|
123
|
-
reference: "
|
|
123
|
+
reference: "before" | "prod" | "both";
|
|
124
124
|
base_branch: string;
|
|
125
125
|
before_ref: string;
|
|
126
126
|
allow_static_preview_fallback: string;
|