@riddledc/riddle-proof 0.7.97 → 0.7.98
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/dist/{chunk-G3UY3SHZ.js → chunk-OMTWNL4B.js} +287 -14
- package/dist/cli.cjs +316 -14
- package/dist/cli.js +30 -1
- package/dist/index.cjs +287 -14
- package/dist/index.js +1 -1
- package/dist/profile.cjs +287 -14
- package/dist/profile.d.cts +7 -1
- package/dist/profile.d.ts +7 -1
- package/dist/profile.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -8758,6 +8758,7 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
|
|
|
8758
8758
|
"frame_no_horizontal_overflow",
|
|
8759
8759
|
"text_visible",
|
|
8760
8760
|
"text_absent",
|
|
8761
|
+
"http_status",
|
|
8761
8762
|
"link_status",
|
|
8762
8763
|
"artifact_link_status",
|
|
8763
8764
|
"route_inventory",
|
|
@@ -9507,16 +9508,27 @@ function normalizeCheck(input, index) {
|
|
|
9507
9508
|
if (type === "route_inventory" && !expectedRoutes?.length) {
|
|
9508
9509
|
throw new Error(`checks[${index}] route_inventory requires expected_routes.`);
|
|
9509
9510
|
}
|
|
9511
|
+
const isHttpStatusCheck = type === "http_status";
|
|
9510
9512
|
const isLinkStatusCheck = type === "link_status" || type === "artifact_link_status";
|
|
9511
|
-
const
|
|
9512
|
-
const
|
|
9513
|
+
const isStatusCheck = isHttpStatusCheck || isLinkStatusCheck;
|
|
9514
|
+
const requestUrl = stringFromOwn(input, "url", "endpoint_url", "endpointUrl", "endpoint", "request_url", "requestUrl", "path");
|
|
9515
|
+
if (isHttpStatusCheck && !requestUrl) {
|
|
9516
|
+
throw new Error(`checks[${index}] http_status requires url.`);
|
|
9517
|
+
}
|
|
9518
|
+
const method = stringFromOwn(input, "method", "http_method", "httpMethod")?.toUpperCase();
|
|
9519
|
+
if (isHttpStatusCheck && method && !/^[A-Z]+$/.test(method)) {
|
|
9520
|
+
throw new Error(`checks[${index}] http_status method must contain only letters.`);
|
|
9521
|
+
}
|
|
9522
|
+
const hasBodyJson = hasOwn(input, "body_json") || hasOwn(input, "bodyJson") || hasOwn(input, "json");
|
|
9523
|
+
const expectedStatus = isStatusCheck ? normalizeHttpStatus(input.expected_status ?? input.expectedStatus ?? input.status, `checks[${index}] expected_status`) : void 0;
|
|
9524
|
+
const allowedStatuses = isStatusCheck ? normalizeHttpStatuses(
|
|
9513
9525
|
input.allowed_statuses ?? input.allowedStatuses ?? input.expected_statuses ?? input.expectedStatuses,
|
|
9514
9526
|
`checks[${index}] allowed_statuses`
|
|
9515
9527
|
) : void 0;
|
|
9516
9528
|
const maxLinks = isLinkStatusCheck ? normalizePositiveInteger(input.max_links ?? input.maxLinks ?? input.limit, `checks[${index}] max_links`, 500) : void 0;
|
|
9517
|
-
const minBytes =
|
|
9518
|
-
const expectedContentType =
|
|
9519
|
-
const allowedContentTypes =
|
|
9529
|
+
const minBytes = isStatusCheck ? normalizePositiveInteger(input.min_bytes ?? input.minBytes ?? input.min_response_bytes ?? input.minResponseBytes, `checks[${index}] min_bytes`) : void 0;
|
|
9530
|
+
const expectedContentType = isStatusCheck ? stringValue5(input.expected_content_type) || stringValue5(input.expectedContentType) || stringValue5(input.content_type) || stringValue5(input.contentType) : void 0;
|
|
9531
|
+
const allowedContentTypes = isStatusCheck ? normalizeStringList(
|
|
9520
9532
|
input.allowed_content_types ?? input.allowedContentTypes ?? input.expected_content_types ?? input.expectedContentTypes,
|
|
9521
9533
|
`checks[${index}] allowed_content_types`
|
|
9522
9534
|
) ?? (expectedContentType ? [expectedContentType] : void 0) : void 0;
|
|
@@ -9537,6 +9549,11 @@ function normalizeCheck(input, index) {
|
|
|
9537
9549
|
expected_url: expectedUrl,
|
|
9538
9550
|
expected_routes: expectedRoutes,
|
|
9539
9551
|
selector: stringValue5(input.selector),
|
|
9552
|
+
url: isHttpStatusCheck ? requestUrl : void 0,
|
|
9553
|
+
method: isHttpStatusCheck ? method || "GET" : void 0,
|
|
9554
|
+
headers: isHttpStatusCheck ? stringRecord(input.headers) : void 0,
|
|
9555
|
+
body: isHttpStatusCheck ? stringValue5(input.body) : void 0,
|
|
9556
|
+
body_json: isHttpStatusCheck && hasBodyJson ? toJsonValue(input.body_json ?? input.bodyJson ?? input.json) : void 0,
|
|
9540
9557
|
expected_texts: expectedTexts,
|
|
9541
9558
|
link_selector: stringValue5(input.link_selector) || stringValue5(input.linkSelector),
|
|
9542
9559
|
source_selector: stringValue5(input.source_selector) || stringValue5(input.sourceSelector),
|
|
@@ -9560,7 +9577,7 @@ function normalizeCheck(input, index) {
|
|
|
9560
9577
|
max_links: maxLinks,
|
|
9561
9578
|
same_origin_only: isLinkStatusCheck ? input.same_origin_only === true || input.sameOriginOnly === true : void 0,
|
|
9562
9579
|
dedupe: isLinkStatusCheck ? input.dedupe === false ? false : true : void 0,
|
|
9563
|
-
require_nonzero_bytes:
|
|
9580
|
+
require_nonzero_bytes: isStatusCheck ? input.require_nonzero_bytes === true || input.requireNonzeroBytes === true : void 0,
|
|
9564
9581
|
min_bytes: minBytes,
|
|
9565
9582
|
allowed_content_types: allowedContentTypes,
|
|
9566
9583
|
allow_get_fallback: isLinkStatusCheck ? input.allow_get_fallback === false || input.allowGetFallback === false ? false : true : void 0,
|
|
@@ -9659,14 +9676,32 @@ function selectorKey(check) {
|
|
|
9659
9676
|
function linkStatusSelector(check) {
|
|
9660
9677
|
return check.selector || check.link_selector || "a[href]";
|
|
9661
9678
|
}
|
|
9662
|
-
function
|
|
9679
|
+
function httpStatusRequestUrl(check, baseUrl) {
|
|
9680
|
+
const rawUrl = check.url || "";
|
|
9681
|
+
if (!rawUrl) return "";
|
|
9682
|
+
try {
|
|
9683
|
+
return baseUrl ? new URL(rawUrl, baseUrl).href : new URL(rawUrl).href;
|
|
9684
|
+
} catch {
|
|
9685
|
+
return rawUrl;
|
|
9686
|
+
}
|
|
9687
|
+
}
|
|
9688
|
+
function httpStatusMethod(check) {
|
|
9689
|
+
return (check.method || "GET").toUpperCase();
|
|
9690
|
+
}
|
|
9691
|
+
function httpStatusKey(check, baseUrl) {
|
|
9692
|
+
return `${httpStatusMethod(check)} ${httpStatusRequestUrl(check, baseUrl)}`;
|
|
9693
|
+
}
|
|
9694
|
+
function httpStatusAllowedStatuses(check) {
|
|
9663
9695
|
if (check.allowed_statuses?.length) return check.allowed_statuses;
|
|
9664
9696
|
if (check.expected_status !== void 0) return [check.expected_status];
|
|
9665
9697
|
return void 0;
|
|
9666
9698
|
}
|
|
9667
|
-
function
|
|
9699
|
+
function linkStatusAllowedStatuses(check) {
|
|
9700
|
+
return httpStatusAllowedStatuses(check);
|
|
9701
|
+
}
|
|
9702
|
+
function httpStatusIsAllowed(status, check) {
|
|
9668
9703
|
if (status === void 0) return false;
|
|
9669
|
-
const allowed =
|
|
9704
|
+
const allowed = httpStatusAllowedStatuses(check);
|
|
9670
9705
|
return allowed?.length ? allowed.includes(status) : status >= 200 && status < 400;
|
|
9671
9706
|
}
|
|
9672
9707
|
function linkStatusObservedBytes(result) {
|
|
@@ -9692,7 +9727,7 @@ function linkStatusContentTypeOk(result, check) {
|
|
|
9692
9727
|
}
|
|
9693
9728
|
function linkStatusResultOk(result, check) {
|
|
9694
9729
|
const status = numberValue3(result.status);
|
|
9695
|
-
if (!
|
|
9730
|
+
if (!httpStatusIsAllowed(status, check)) return false;
|
|
9696
9731
|
if (stringValue5(result.error)) return false;
|
|
9697
9732
|
if (result.ok === false) return false;
|
|
9698
9733
|
if (!linkStatusContentTypeOk(result, check)) return false;
|
|
@@ -9706,6 +9741,54 @@ function linkStatusResultOk(result, check) {
|
|
|
9706
9741
|
}
|
|
9707
9742
|
return true;
|
|
9708
9743
|
}
|
|
9744
|
+
function httpStatusEvidenceForCheck(viewport, check) {
|
|
9745
|
+
const evidence = viewport.http_statuses?.[httpStatusKey(check, viewport.url)];
|
|
9746
|
+
return isRecord2(evidence) ? evidence : void 0;
|
|
9747
|
+
}
|
|
9748
|
+
function summarizeHttpStatusEvidence(viewport, check) {
|
|
9749
|
+
const key = httpStatusKey(check, viewport.url);
|
|
9750
|
+
const statusEvidence = httpStatusEvidenceForCheck(viewport, check);
|
|
9751
|
+
if (!statusEvidence) {
|
|
9752
|
+
return {
|
|
9753
|
+
viewport: viewport.name,
|
|
9754
|
+
key,
|
|
9755
|
+
url: httpStatusRequestUrl(check, viewport.url),
|
|
9756
|
+
method: httpStatusMethod(check),
|
|
9757
|
+
ok: false,
|
|
9758
|
+
status: null,
|
|
9759
|
+
failures: [{ code: "http_status_evidence_missing" }]
|
|
9760
|
+
};
|
|
9761
|
+
}
|
|
9762
|
+
const failures = [];
|
|
9763
|
+
if (!linkStatusResultOk(statusEvidence, check)) {
|
|
9764
|
+
failures.push({
|
|
9765
|
+
code: "http_status_failed",
|
|
9766
|
+
url: stringValue5(statusEvidence.url) ?? httpStatusRequestUrl(check, viewport.url),
|
|
9767
|
+
status: numberValue3(statusEvidence.status) ?? null,
|
|
9768
|
+
method: stringValue5(statusEvidence.method) ?? httpStatusMethod(check),
|
|
9769
|
+
error: stringValue5(statusEvidence.error) ?? null,
|
|
9770
|
+
content_type: stringValue5(statusEvidence.content_type) ?? null,
|
|
9771
|
+
bytes: linkStatusObservedBytes(statusEvidence) ?? null,
|
|
9772
|
+
allowed_statuses: httpStatusAllowedStatuses(check) ?? ["2xx", "3xx"],
|
|
9773
|
+
min_bytes: check.min_bytes ?? null,
|
|
9774
|
+
allowed_content_types: check.allowed_content_types ?? null
|
|
9775
|
+
});
|
|
9776
|
+
}
|
|
9777
|
+
return {
|
|
9778
|
+
viewport: viewport.name,
|
|
9779
|
+
key,
|
|
9780
|
+
url: stringValue5(statusEvidence.url) ?? httpStatusRequestUrl(check, viewport.url),
|
|
9781
|
+
method: stringValue5(statusEvidence.method) ?? httpStatusMethod(check),
|
|
9782
|
+
status: numberValue3(statusEvidence.status) ?? null,
|
|
9783
|
+
status_text: stringValue5(statusEvidence.status_text) ?? null,
|
|
9784
|
+
ok: failures.length === 0,
|
|
9785
|
+
error: stringValue5(statusEvidence.error) ?? null,
|
|
9786
|
+
content_type: stringValue5(statusEvidence.content_type) ?? null,
|
|
9787
|
+
content_length: numberValue3(statusEvidence.content_length) ?? null,
|
|
9788
|
+
bytes: linkStatusObservedBytes(statusEvidence) ?? null,
|
|
9789
|
+
failures
|
|
9790
|
+
};
|
|
9791
|
+
}
|
|
9709
9792
|
function linkStatusEvidenceForCheck(viewport, check) {
|
|
9710
9793
|
const evidence = viewport.link_statuses?.[linkStatusSelector(check)];
|
|
9711
9794
|
return isRecord2(evidence) ? evidence : void 0;
|
|
@@ -10296,6 +10379,28 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
10296
10379
|
message: failed ? `Text assertion failed in ${failed} viewport(s).` : void 0
|
|
10297
10380
|
};
|
|
10298
10381
|
}
|
|
10382
|
+
if (check.type === "http_status") {
|
|
10383
|
+
const url = httpStatusRequestUrl(check, evidence.target_url);
|
|
10384
|
+
const method = httpStatusMethod(check);
|
|
10385
|
+
const summaries = viewports.map((viewport) => summarizeHttpStatusEvidence(viewport, check));
|
|
10386
|
+
const failed = summaries.filter((summary) => Array.isArray(summary.failures) && summary.failures.length > 0);
|
|
10387
|
+
return {
|
|
10388
|
+
type: check.type,
|
|
10389
|
+
label: checkLabel(check),
|
|
10390
|
+
status: failed.length ? "failed" : "passed",
|
|
10391
|
+
evidence: {
|
|
10392
|
+
url,
|
|
10393
|
+
method,
|
|
10394
|
+
allowed_statuses: httpStatusAllowedStatuses(check) || ["2xx", "3xx"],
|
|
10395
|
+
require_nonzero_bytes: check.require_nonzero_bytes === true,
|
|
10396
|
+
min_bytes: check.min_bytes ?? null,
|
|
10397
|
+
allowed_content_types: check.allowed_content_types ?? null,
|
|
10398
|
+
viewports: summaries.map((summary) => toJsonValue(summary)),
|
|
10399
|
+
failures: failed.flatMap((summary) => Array.isArray(summary.failures) ? summary.failures.map((failure) => toJsonValue({ viewport: stringValue5(summary.viewport) ?? null, failure })) : [])
|
|
10400
|
+
},
|
|
10401
|
+
message: failed.length ? `HTTP status failed in ${failed.length} viewport(s).` : void 0
|
|
10402
|
+
};
|
|
10403
|
+
}
|
|
10299
10404
|
if (check.type === "link_status" || check.type === "artifact_link_status") {
|
|
10300
10405
|
const selector = linkStatusSelector(check);
|
|
10301
10406
|
const summaries = viewports.map((viewport) => summarizeLinkStatusEvidence(viewport, check));
|
|
@@ -10905,16 +11010,37 @@ function textOrderMatch(texts, expectedTexts) {
|
|
|
10905
11010
|
function linkStatusSelector(check) {
|
|
10906
11011
|
return check.selector || check.link_selector || "a[href]";
|
|
10907
11012
|
}
|
|
10908
|
-
function
|
|
11013
|
+
function httpStatusRequestUrl(check, baseUrl) {
|
|
11014
|
+
const rawUrl = check.url || "";
|
|
11015
|
+
if (!rawUrl) return "";
|
|
11016
|
+
try {
|
|
11017
|
+
return baseUrl ? new URL(rawUrl, baseUrl).href : new URL(rawUrl).href;
|
|
11018
|
+
} catch {
|
|
11019
|
+
return rawUrl;
|
|
11020
|
+
}
|
|
11021
|
+
}
|
|
11022
|
+
function httpStatusMethod(check) {
|
|
11023
|
+
return String(check.method || "GET").toUpperCase();
|
|
11024
|
+
}
|
|
11025
|
+
function httpStatusKey(check, baseUrl) {
|
|
11026
|
+
return httpStatusMethod(check) + " " + httpStatusRequestUrl(check, baseUrl);
|
|
11027
|
+
}
|
|
11028
|
+
function httpStatusAllowedStatuses(check) {
|
|
10909
11029
|
if (Array.isArray(check.allowed_statuses) && check.allowed_statuses.length) return check.allowed_statuses;
|
|
10910
11030
|
if (typeof check.expected_status === "number" && Number.isFinite(check.expected_status)) return [check.expected_status];
|
|
10911
11031
|
return undefined;
|
|
10912
11032
|
}
|
|
10913
|
-
function
|
|
11033
|
+
function linkStatusAllowedStatuses(check) {
|
|
11034
|
+
return httpStatusAllowedStatuses(check);
|
|
11035
|
+
}
|
|
11036
|
+
function httpStatusIsAllowed(status, check) {
|
|
10914
11037
|
if (typeof status !== "number" || !Number.isFinite(status)) return false;
|
|
10915
|
-
const allowed =
|
|
11038
|
+
const allowed = httpStatusAllowedStatuses(check);
|
|
10916
11039
|
return Array.isArray(allowed) && allowed.length ? allowed.includes(status) : status >= 200 && status < 400;
|
|
10917
11040
|
}
|
|
11041
|
+
function linkStatusIsAllowed(status, check) {
|
|
11042
|
+
return httpStatusIsAllowed(status, check);
|
|
11043
|
+
}
|
|
10918
11044
|
function linkStatusObservedBytes(result) {
|
|
10919
11045
|
const bytes = typeof result.bytes === "number" && Number.isFinite(result.bytes) ? result.bytes : undefined;
|
|
10920
11046
|
const contentLength = typeof result.content_length === "number" && Number.isFinite(result.content_length) ? result.content_length : undefined;
|
|
@@ -10939,7 +11065,7 @@ function linkStatusContentTypeOk(result, check) {
|
|
|
10939
11065
|
}
|
|
10940
11066
|
function linkStatusResultOk(result, check) {
|
|
10941
11067
|
if (!result || typeof result !== "object" || Array.isArray(result)) return false;
|
|
10942
|
-
if (!
|
|
11068
|
+
if (!httpStatusIsAllowed(result.status, check)) return false;
|
|
10943
11069
|
if (typeof result.error === "string" && result.error.trim()) return false;
|
|
10944
11070
|
if (result.ok === false) return false;
|
|
10945
11071
|
if (!linkStatusContentTypeOk(result, check)) return false;
|
|
@@ -10953,6 +11079,50 @@ function linkStatusResultOk(result, check) {
|
|
|
10953
11079
|
}
|
|
10954
11080
|
return true;
|
|
10955
11081
|
}
|
|
11082
|
+
function summarizeHttpStatusEvidence(viewport, check) {
|
|
11083
|
+
const key = httpStatusKey(check, viewport && viewport.url);
|
|
11084
|
+
const statusEvidence = viewport && viewport.http_statuses && viewport.http_statuses[key];
|
|
11085
|
+
if (!statusEvidence || typeof statusEvidence !== "object" || Array.isArray(statusEvidence)) {
|
|
11086
|
+
return {
|
|
11087
|
+
viewport: viewport && viewport.name,
|
|
11088
|
+
key,
|
|
11089
|
+
url: httpStatusRequestUrl(check, viewport && viewport.url),
|
|
11090
|
+
method: httpStatusMethod(check),
|
|
11091
|
+
ok: false,
|
|
11092
|
+
status: null,
|
|
11093
|
+
failures: [{ code: "http_status_evidence_missing" }],
|
|
11094
|
+
};
|
|
11095
|
+
}
|
|
11096
|
+
const failures = [];
|
|
11097
|
+
if (!linkStatusResultOk(statusEvidence, check)) {
|
|
11098
|
+
failures.push({
|
|
11099
|
+
code: "http_status_failed",
|
|
11100
|
+
url: typeof statusEvidence.url === "string" ? statusEvidence.url : httpStatusRequestUrl(check, viewport && viewport.url),
|
|
11101
|
+
status: typeof statusEvidence.status === "number" && Number.isFinite(statusEvidence.status) ? statusEvidence.status : null,
|
|
11102
|
+
method: typeof statusEvidence.method === "string" ? statusEvidence.method : httpStatusMethod(check),
|
|
11103
|
+
error: typeof statusEvidence.error === "string" ? statusEvidence.error : null,
|
|
11104
|
+
content_type: typeof statusEvidence.content_type === "string" ? statusEvidence.content_type : null,
|
|
11105
|
+
bytes: linkStatusObservedBytes(statusEvidence) ?? null,
|
|
11106
|
+
allowed_statuses: httpStatusAllowedStatuses(check) || ["2xx", "3xx"],
|
|
11107
|
+
min_bytes: typeof check.min_bytes === "number" && Number.isFinite(check.min_bytes) ? check.min_bytes : null,
|
|
11108
|
+
allowed_content_types: Array.isArray(check.allowed_content_types) ? check.allowed_content_types : null,
|
|
11109
|
+
});
|
|
11110
|
+
}
|
|
11111
|
+
return {
|
|
11112
|
+
viewport: viewport && viewport.name,
|
|
11113
|
+
key,
|
|
11114
|
+
url: typeof statusEvidence.url === "string" ? statusEvidence.url : httpStatusRequestUrl(check, viewport && viewport.url),
|
|
11115
|
+
method: typeof statusEvidence.method === "string" ? statusEvidence.method : httpStatusMethod(check),
|
|
11116
|
+
status: typeof statusEvidence.status === "number" && Number.isFinite(statusEvidence.status) ? statusEvidence.status : null,
|
|
11117
|
+
status_text: typeof statusEvidence.status_text === "string" ? statusEvidence.status_text : null,
|
|
11118
|
+
ok: failures.length === 0,
|
|
11119
|
+
error: typeof statusEvidence.error === "string" ? statusEvidence.error : null,
|
|
11120
|
+
content_type: typeof statusEvidence.content_type === "string" ? statusEvidence.content_type : null,
|
|
11121
|
+
content_length: typeof statusEvidence.content_length === "number" && Number.isFinite(statusEvidence.content_length) ? statusEvidence.content_length : null,
|
|
11122
|
+
bytes: linkStatusObservedBytes(statusEvidence) ?? null,
|
|
11123
|
+
failures,
|
|
11124
|
+
};
|
|
11125
|
+
}
|
|
10956
11126
|
function summarizeLinkStatusEvidence(viewport, check) {
|
|
10957
11127
|
const selector = linkStatusSelector(check);
|
|
10958
11128
|
const linkEvidence = viewport && viewport.link_statuses && viewport.link_statuses[selector];
|
|
@@ -11708,6 +11878,31 @@ function assessProfile(profile, evidence) {
|
|
|
11708
11878
|
});
|
|
11709
11879
|
continue;
|
|
11710
11880
|
}
|
|
11881
|
+
if (check.type === "http_status") {
|
|
11882
|
+
const url = httpStatusRequestUrl(check, evidence.target_url);
|
|
11883
|
+
const method = httpStatusMethod(check);
|
|
11884
|
+
const summaries = checkViewports.map((viewport) => summarizeHttpStatusEvidence(viewport, check));
|
|
11885
|
+
const failed = summaries.filter((summary) => Array.isArray(summary.failures) && summary.failures.length > 0);
|
|
11886
|
+
checks.push({
|
|
11887
|
+
type: check.type,
|
|
11888
|
+
label: check.label || check.type,
|
|
11889
|
+
status: failed.length ? "failed" : "passed",
|
|
11890
|
+
evidence: {
|
|
11891
|
+
url,
|
|
11892
|
+
method,
|
|
11893
|
+
allowed_statuses: httpStatusAllowedStatuses(check) || ["2xx", "3xx"],
|
|
11894
|
+
require_nonzero_bytes: check.require_nonzero_bytes === true,
|
|
11895
|
+
min_bytes: check.min_bytes ?? null,
|
|
11896
|
+
allowed_content_types: check.allowed_content_types ?? null,
|
|
11897
|
+
viewports: summaries,
|
|
11898
|
+
failures: failed.flatMap((summary) => Array.isArray(summary.failures)
|
|
11899
|
+
? summary.failures.map((failure) => ({ viewport: summary.viewport || null, failure }))
|
|
11900
|
+
: []),
|
|
11901
|
+
},
|
|
11902
|
+
message: failed.length ? "HTTP status failed in " + failed.length + " viewport(s)." : undefined,
|
|
11903
|
+
});
|
|
11904
|
+
continue;
|
|
11905
|
+
}
|
|
11711
11906
|
if (check.type === "link_status" || check.type === "artifact_link_status") {
|
|
11712
11907
|
const selector = linkStatusSelector(check);
|
|
11713
11908
|
const summaries = checkViewports.map((viewport) => summarizeLinkStatusEvidence(viewport, check));
|
|
@@ -12905,6 +13100,65 @@ function linkProbeResponseFields(response, method) {
|
|
|
12905
13100
|
content_length: contentLength,
|
|
12906
13101
|
};
|
|
12907
13102
|
}
|
|
13103
|
+
async function collectHttpStatus(check) {
|
|
13104
|
+
const url = httpStatusRequestUrl(check, page.url() || targetUrl);
|
|
13105
|
+
const method = httpStatusMethod(check);
|
|
13106
|
+
const headers = check.headers && typeof check.headers === "object" && !Array.isArray(check.headers)
|
|
13107
|
+
? Object.fromEntries(Object.entries(check.headers).map(([key, value]) => [key, String(value)]).filter(([key]) => key.trim()))
|
|
13108
|
+
: {};
|
|
13109
|
+
let body;
|
|
13110
|
+
if (check.body_json !== undefined) {
|
|
13111
|
+
body = JSON.stringify(check.body_json);
|
|
13112
|
+
if (!Object.keys(headers).some((key) => key.toLowerCase() === "content-type")) headers["content-type"] = "application/json";
|
|
13113
|
+
} else if (typeof check.body === "string") {
|
|
13114
|
+
body = check.body;
|
|
13115
|
+
}
|
|
13116
|
+
const options = {
|
|
13117
|
+
method,
|
|
13118
|
+
redirect: "follow",
|
|
13119
|
+
cache: "no-store",
|
|
13120
|
+
headers,
|
|
13121
|
+
};
|
|
13122
|
+
if (body !== undefined && method !== "GET" && method !== "HEAD") options.body = body;
|
|
13123
|
+
const result = {
|
|
13124
|
+
version: "riddle-proof.http-status.v1",
|
|
13125
|
+
url,
|
|
13126
|
+
method,
|
|
13127
|
+
status: null,
|
|
13128
|
+
ok: false,
|
|
13129
|
+
error: null,
|
|
13130
|
+
request_body_bytes: typeof body === "string" ? body.length : 0,
|
|
13131
|
+
allowed_statuses: httpStatusAllowedStatuses(check) || ["2xx", "3xx"],
|
|
13132
|
+
require_nonzero_bytes: check.require_nonzero_bytes === true,
|
|
13133
|
+
min_bytes: typeof check.min_bytes === "number" && Number.isFinite(check.min_bytes) ? check.min_bytes : null,
|
|
13134
|
+
allowed_content_types: Array.isArray(check.allowed_content_types) ? check.allowed_content_types : null,
|
|
13135
|
+
};
|
|
13136
|
+
try {
|
|
13137
|
+
const response = await fetch(url, options);
|
|
13138
|
+
Object.assign(result, linkProbeResponseFields(response, method));
|
|
13139
|
+
result.url = url;
|
|
13140
|
+
result.status_text = response.statusText || "";
|
|
13141
|
+
const shouldReadBody = check.require_nonzero_bytes === true || (typeof check.min_bytes === "number" && Number.isFinite(check.min_bytes));
|
|
13142
|
+
if (shouldReadBody) {
|
|
13143
|
+
try {
|
|
13144
|
+
const buffer = await response.arrayBuffer();
|
|
13145
|
+
result.bytes = buffer.byteLength;
|
|
13146
|
+
} catch (error) {
|
|
13147
|
+
result.error = String(error && error.message ? error.message : error).slice(0, 500);
|
|
13148
|
+
}
|
|
13149
|
+
}
|
|
13150
|
+
result.ok = linkProbeAllowed(result.status, check)
|
|
13151
|
+
&& linkProbeContentTypeAllowed(result, check)
|
|
13152
|
+
&& (check.require_nonzero_bytes !== true || ((linkProbeObservedBytes(result) || 0) > 0))
|
|
13153
|
+
&& (!(typeof check.min_bytes === "number" && Number.isFinite(check.min_bytes)) || ((linkProbeObservedBytes(result) || 0) >= check.min_bytes))
|
|
13154
|
+
&& !result.error;
|
|
13155
|
+
return result;
|
|
13156
|
+
} catch (error) {
|
|
13157
|
+
result.error = String(error && error.message ? error.message : error).slice(0, 500);
|
|
13158
|
+
result.ok = false;
|
|
13159
|
+
return result;
|
|
13160
|
+
}
|
|
13161
|
+
}
|
|
12908
13162
|
async function probeLinkStatus(candidate, check) {
|
|
12909
13163
|
const requireNonzeroBytes = check.require_nonzero_bytes === true;
|
|
12910
13164
|
const minBytes = typeof check.min_bytes === "number" && Number.isFinite(check.min_bytes) ? Math.max(1, Math.floor(check.min_bytes)) : null;
|
|
@@ -13597,6 +13851,7 @@ async function captureViewport(viewport) {
|
|
|
13597
13851
|
const frames = {};
|
|
13598
13852
|
const text_sequences = {};
|
|
13599
13853
|
const text_matches = {};
|
|
13854
|
+
const http_statuses = {};
|
|
13600
13855
|
const link_statuses = {};
|
|
13601
13856
|
for (const check of profile.checks || []) {
|
|
13602
13857
|
if (!profileCheckAppliesToViewport(check, viewport)) continue;
|
|
@@ -13623,6 +13878,10 @@ async function captureViewport(viewport) {
|
|
|
13623
13878
|
selectors[check.selector] = selectors[check.selector] || await selectorStats(check.selector);
|
|
13624
13879
|
frames[check.selector] = frames[check.selector] || await frameEvidence(check.selector);
|
|
13625
13880
|
}
|
|
13881
|
+
if (check.type === "http_status") {
|
|
13882
|
+
const key = httpStatusKey(check, page.url() || targetUrl);
|
|
13883
|
+
http_statuses[key] = http_statuses[key] || await collectHttpStatus(check);
|
|
13884
|
+
}
|
|
13626
13885
|
if (check.type === "link_status" || check.type === "artifact_link_status") {
|
|
13627
13886
|
const selector = linkStatusSelector(check);
|
|
13628
13887
|
link_statuses[selector] = link_statuses[selector] || await collectLinkStatus(check);
|
|
@@ -13690,6 +13949,7 @@ async function captureViewport(viewport) {
|
|
|
13690
13949
|
frames,
|
|
13691
13950
|
text_sequences,
|
|
13692
13951
|
text_matches,
|
|
13952
|
+
http_statuses,
|
|
13693
13953
|
link_statuses,
|
|
13694
13954
|
route_inventory: routeInventory,
|
|
13695
13955
|
setup_action_results: setupActionResults,
|
|
@@ -13739,6 +13999,19 @@ function buildProfileEvidence(currentViewports) {
|
|
|
13739
13999
|
),
|
|
13740
14000
|
})),
|
|
13741
14001
|
})),
|
|
14002
|
+
http_status: currentViewports
|
|
14003
|
+
.filter((viewport) => viewport.http_statuses && Object.keys(viewport.http_statuses).length)
|
|
14004
|
+
.map((viewport) => ({
|
|
14005
|
+
viewport: viewport.name,
|
|
14006
|
+
requests: Object.entries(viewport.http_statuses || {}).map(([key, statusSet]) => ({
|
|
14007
|
+
key,
|
|
14008
|
+
url: statusSet && statusSet.url,
|
|
14009
|
+
method: statusSet && statusSet.method,
|
|
14010
|
+
status: statusSet && statusSet.status,
|
|
14011
|
+
ok: statusSet && statusSet.ok === true,
|
|
14012
|
+
error: statusSet && statusSet.error,
|
|
14013
|
+
})),
|
|
14014
|
+
})),
|
|
13742
14015
|
link_status: currentViewports
|
|
13743
14016
|
.filter((viewport) => viewport.link_statuses && Object.keys(viewport.link_statuses).length)
|
|
13744
14017
|
.map((viewport) => ({
|
package/dist/index.js
CHANGED
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
resolveRiddleProofProfileTimeoutSec,
|
|
59
59
|
slugifyRiddleProofProfileName,
|
|
60
60
|
summarizeRiddleProofProfileResult
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-OMTWNL4B.js";
|
|
62
62
|
import {
|
|
63
63
|
DEFAULT_RIDDLE_API_BASE_URL,
|
|
64
64
|
DEFAULT_RIDDLE_API_KEY_FILE,
|