@riddledc/riddle-proof 0.7.38 → 0.7.40

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/profile.cjs CHANGED
@@ -289,24 +289,57 @@ function normalizeNetworkMock(input, index) {
289
289
  if (!isRecord(input)) throw new Error(`target.network_mocks[${index}] must be an object.`);
290
290
  const url = stringValue(input.url) || stringValue(input.glob) || stringValue(input.pattern);
291
291
  if (!url) throw new Error(`target.network_mocks[${index}] requires url.`);
292
- const status = numberValue(input.status) ?? 200;
293
- if (!Number.isInteger(status) || status < 100 || status > 599) {
294
- throw new Error(`target.network_mocks[${index}].status must be an HTTP status code.`);
292
+ const payload = normalizeNetworkMockResponsePayload(input, `target.network_mocks[${index}]`);
293
+ const responsesInput = input.responses ?? input.sequence;
294
+ const responses = normalizeNetworkMockResponses(responsesInput, index, payload);
295
+ const requiredHitCount = numberValue(
296
+ input.required_hit_count ?? input.requiredHitCount ?? input.required_hits ?? input.requiredHits ?? input.min_hits ?? input.minHits
297
+ );
298
+ if (requiredHitCount !== void 0 && (!Number.isInteger(requiredHitCount) || requiredHitCount < 1)) {
299
+ throw new Error(`target.network_mocks[${index}].required_hit_count must be a positive integer.`);
295
300
  }
296
- const body = stringValue(input.body) ?? stringValue(input.body_text) ?? stringValue(input.bodyText);
297
- const hasJsonBody = Object.prototype.hasOwnProperty.call(input, "body_json") || Object.prototype.hasOwnProperty.call(input, "bodyJson") || Object.prototype.hasOwnProperty.call(input, "json");
298
301
  return {
302
+ ...payload,
299
303
  label: normalizeName(input.label || input.name, `network-mock-${index + 1}`),
300
304
  url,
301
305
  method: stringValue(input.method)?.toUpperCase(),
306
+ responses,
307
+ required_hit_count: requiredHitCount,
308
+ required: input.required === false ? false : true
309
+ };
310
+ }
311
+ function normalizeNetworkMockResponsePayload(input, label, defaults = {}) {
312
+ const status = numberValue(input.status) ?? defaults.status ?? 200;
313
+ if (!Number.isInteger(status) || status < 100 || status > 599) {
314
+ throw new Error(`${label}.status must be an HTTP status code.`);
315
+ }
316
+ const body = stringValue(input.body) ?? stringValue(input.body_text) ?? stringValue(input.bodyText) ?? defaults.body;
317
+ const hasJsonBody = Object.prototype.hasOwnProperty.call(input, "body_json") || Object.prototype.hasOwnProperty.call(input, "bodyJson") || Object.prototype.hasOwnProperty.call(input, "json");
318
+ return {
319
+ label: stringValue(input.label) || stringValue(input.name) || defaults.label,
302
320
  status,
303
- content_type: stringValue(input.content_type) || stringValue(input.contentType),
304
- headers: stringRecord(input.headers),
321
+ content_type: stringValue(input.content_type) || stringValue(input.contentType) || defaults.content_type,
322
+ headers: stringRecord(input.headers) || defaults.headers,
305
323
  body,
306
- body_json: hasJsonBody ? toJsonValue(input.body_json ?? input.bodyJson ?? input.json) : void 0,
307
- required: input.required === false ? false : true
324
+ body_json: hasJsonBody ? toJsonValue(input.body_json ?? input.bodyJson ?? input.json) : defaults.body_json
308
325
  };
309
326
  }
327
+ function normalizeNetworkMockResponses(value, mockIndex, defaults) {
328
+ if (value === void 0) return void 0;
329
+ if (!Array.isArray(value)) throw new Error(`target.network_mocks[${mockIndex}].responses must be an array.`);
330
+ if (!value.length) throw new Error(`target.network_mocks[${mockIndex}].responses must not be empty.`);
331
+ const responseDefaults = { ...defaults, label: void 0 };
332
+ return value.map((response, responseIndex) => {
333
+ if (!isRecord(response)) {
334
+ throw new Error(`target.network_mocks[${mockIndex}].responses[${responseIndex}] must be an object.`);
335
+ }
336
+ return normalizeNetworkMockResponsePayload(
337
+ response,
338
+ `target.network_mocks[${mockIndex}].responses[${responseIndex}]`,
339
+ responseDefaults
340
+ );
341
+ });
342
+ }
310
343
  function normalizeNetworkMocks(value) {
311
344
  if (value === void 0) return void 0;
312
345
  if (!Array.isArray(value)) throw new Error("target.network_mocks must be an array.");
@@ -348,6 +381,13 @@ function normalizeExpectedTexts(value, index) {
348
381
  if (!texts.length) throw new Error(`checks[${index}] selector_text_order expected_texts must contain non-empty strings.`);
349
382
  return texts;
350
383
  }
384
+ function normalizeStringList(value, label) {
385
+ if (value === void 0) return void 0;
386
+ if (!Array.isArray(value)) throw new Error(`${label} must be an array.`);
387
+ const values = value.map((item) => String(item).replace(/\s+/g, " ").trim()).filter(Boolean);
388
+ if (!values.length) throw new Error(`${label} must contain non-empty strings.`);
389
+ return values;
390
+ }
351
391
  function normalizeCheck(input, index) {
352
392
  if (!isRecord(input)) throw new Error(`checks[${index}] must be an object.`);
353
393
  const type = stringValue(input.type);
@@ -396,6 +436,10 @@ function normalizeCheck(input, index) {
396
436
  text: stringValue(input.text),
397
437
  pattern: stringValue(input.pattern),
398
438
  flags: stringValue(input.flags),
439
+ allowed_console_texts: normalizeStringList(input.allowed_console_texts ?? input.allowedConsoleTexts ?? input.allow_console_texts ?? input.allowConsoleTexts, `checks[${index}] allowed_console_texts`),
440
+ allowed_console_patterns: normalizeStringList(input.allowed_console_patterns ?? input.allowedConsolePatterns ?? input.allow_console_patterns ?? input.allowConsolePatterns, `checks[${index}] allowed_console_patterns`),
441
+ 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`),
442
+ 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`),
399
443
  min_count: numberValue(input.min_count),
400
444
  max_overflow_px: numberValue(input.max_overflow_px),
401
445
  timeout_ms: numberValue(input.timeout_ms) ?? numberValue(input.timeoutMs),
@@ -559,6 +603,18 @@ function matchText(sample, check) {
559
603
  }
560
604
  return sample.includes(check.text || "");
561
605
  }
606
+ function matchesAllowedMessage(message, texts, patterns) {
607
+ const sample = String(message || "");
608
+ if (texts?.some((text) => sample.includes(text))) return true;
609
+ for (const pattern of patterns || []) {
610
+ try {
611
+ if (new RegExp(pattern).test(sample)) return true;
612
+ } catch {
613
+ continue;
614
+ }
615
+ }
616
+ return false;
617
+ }
562
618
  function normalizeRoutePath(path) {
563
619
  const value = path || "/";
564
620
  if (value === "/") return "/";
@@ -845,14 +901,28 @@ function assessCheckFromEvidence(check, evidence) {
845
901
  };
846
902
  }
847
903
  if (check.type === "no_fatal_console_errors") {
848
- const fatalCount = (evidence.console?.fatal_count || 0) + (evidence.page_errors?.length || 0);
904
+ const fatalConsoleEvents = (evidence.console?.events || []).filter((event) => event.type === "error" || event.type === "assert");
905
+ const allowedConsoleEvents = fatalConsoleEvents.filter((event) => matchesAllowedMessage(event.text, check.allowed_console_texts, check.allowed_console_patterns));
906
+ const unallowedConsoleEvents = fatalConsoleEvents.filter((event) => !matchesAllowedMessage(event.text, check.allowed_console_texts, check.allowed_console_patterns));
907
+ const pageErrors = evidence.page_errors || [];
908
+ const allowedPageErrors = pageErrors.filter((error) => matchesAllowedMessage(error.message, check.allowed_page_error_texts, check.allowed_page_error_patterns));
909
+ const unallowedPageErrors = pageErrors.filter((error) => !matchesAllowedMessage(error.message, check.allowed_page_error_texts, check.allowed_page_error_patterns));
910
+ const fatalCount = unallowedConsoleEvents.length + unallowedPageErrors.length;
849
911
  return {
850
912
  type: check.type,
851
913
  label: checkLabel(check),
852
914
  status: fatalCount ? "failed" : "passed",
853
915
  evidence: {
854
- console_fatal_count: evidence.console?.fatal_count || 0,
855
- page_error_count: evidence.page_errors?.length || 0
916
+ console_fatal_count: unallowedConsoleEvents.length,
917
+ page_error_count: unallowedPageErrors.length,
918
+ total_console_fatal_count: fatalConsoleEvents.length,
919
+ total_page_error_count: pageErrors.length,
920
+ allowed_console_fatal_count: allowedConsoleEvents.length,
921
+ allowed_page_error_count: allowedPageErrors.length,
922
+ allowed_console_texts: check.allowed_console_texts || [],
923
+ allowed_console_patterns: check.allowed_console_patterns || [],
924
+ allowed_page_error_texts: check.allowed_page_error_texts || [],
925
+ allowed_page_error_patterns: check.allowed_page_error_patterns || []
856
926
  },
857
927
  message: fatalCount ? `${fatalCount} fatal browser error(s) were captured.` : void 0
858
928
  };
@@ -915,12 +985,15 @@ function assessNetworkMocksFromEvidence(profile, evidence) {
915
985
  const requiredMocks = mocks.filter((mock) => mock.required !== false);
916
986
  for (const mock of requiredMocks) {
917
987
  const hits = events.filter((event) => event.label === mock.label && event.ok !== false).length;
918
- if (hits < 1) {
988
+ const requiredHitCount = requiredNetworkMockHitCount(mock);
989
+ if (hits < requiredHitCount) {
919
990
  failed.push({
920
991
  label: mock.label,
921
992
  url: mock.url,
922
993
  method: mock.method || null,
923
- reason: "required_mock_not_hit"
994
+ reason: hits < 1 ? "required_mock_not_hit" : "required_mock_hit_count_not_met",
995
+ required_hit_count: requiredHitCount,
996
+ hit_count: hits
924
997
  });
925
998
  }
926
999
  }
@@ -946,11 +1019,21 @@ function assessNetworkMocksFromEvidence(profile, evidence) {
946
1019
  mock.label,
947
1020
  events.filter((event) => event.label === mock.label && event.ok !== false).length
948
1021
  ])),
1022
+ required_hits_by_label: Object.fromEntries(requiredMocks.map((mock) => [
1023
+ mock.label,
1024
+ requiredNetworkMockHitCount(mock)
1025
+ ])),
949
1026
  failed
950
1027
  },
951
1028
  message: failed.length ? `Network mocks failed or were not hit for ${failed.length} mock(s).` : void 0
952
1029
  };
953
1030
  }
1031
+ function requiredNetworkMockHitCount(mock) {
1032
+ if (mock.required === false) return 0;
1033
+ if (mock.required_hit_count !== void 0) return mock.required_hit_count;
1034
+ if (Array.isArray(mock.responses) && mock.responses.length) return mock.responses.length;
1035
+ return 1;
1036
+ }
954
1037
  function profileStatusFromEvidence(profile, evidence, checks) {
955
1038
  if (!evidence) return "proof_insufficient";
956
1039
  const viewports = evidence.viewports || [];
@@ -1108,6 +1191,16 @@ function textMatches(sample, check) {
1108
1191
  }
1109
1192
  return String(sample || "").includes(check.text || "");
1110
1193
  }
1194
+ function matchesAllowedMessage(message, texts, patterns) {
1195
+ const sample = String(message || "");
1196
+ if ((texts || []).some((text) => sample.includes(text))) return true;
1197
+ for (const pattern of patterns || []) {
1198
+ try {
1199
+ if (new RegExp(pattern).test(sample)) return true;
1200
+ } catch {}
1201
+ }
1202
+ return false;
1203
+ }
1111
1204
  function textSequenceForCheck(viewport, check) {
1112
1205
  const key = check.selector || "";
1113
1206
  const sequence = viewport.text_sequences && viewport.text_sequences[key];
@@ -1235,6 +1328,12 @@ function horizontalBoundsOverflowPx(value) {
1235
1328
  }
1236
1329
  return roundPixels(max);
1237
1330
  }
1331
+ function requiredNetworkMockHitCount(mock) {
1332
+ if (!mock || mock.required === false) return 0;
1333
+ if (Number.isInteger(mock.required_hit_count) && mock.required_hit_count > 0) return mock.required_hit_count;
1334
+ if (Array.isArray(mock.responses) && mock.responses.length) return mock.responses.length;
1335
+ return 1;
1336
+ }
1238
1337
  function assessProfile(profile, evidence) {
1239
1338
  const checks = [];
1240
1339
  const viewports = evidence.viewports || [];
@@ -1244,12 +1343,15 @@ function assessProfile(profile, evidence) {
1244
1343
  const failed = [];
1245
1344
  for (const mock of requiredMocks) {
1246
1345
  const hits = events.filter((event) => event && event.label === mock.label && event.ok !== false).length;
1247
- if (hits < 1) {
1346
+ const requiredHitCount = requiredNetworkMockHitCount(mock);
1347
+ if (hits < requiredHitCount) {
1248
1348
  failed.push({
1249
1349
  label: mock.label,
1250
1350
  url: mock.url,
1251
1351
  method: mock.method || null,
1252
- reason: "required_mock_not_hit",
1352
+ reason: hits < 1 ? "required_mock_not_hit" : "required_mock_hit_count_not_met",
1353
+ required_hit_count: requiredHitCount,
1354
+ hit_count: hits,
1253
1355
  });
1254
1356
  }
1255
1357
  }
@@ -1264,8 +1366,10 @@ function assessProfile(profile, evidence) {
1264
1366
  }
1265
1367
  }
1266
1368
  const hitsByLabel = {};
1369
+ const requiredHitsByLabel = {};
1267
1370
  for (const mock of profile.target.network_mocks) {
1268
1371
  hitsByLabel[mock.label] = events.filter((event) => event && event.label === mock.label && event.ok !== false).length;
1372
+ if (mock && mock.required !== false) requiredHitsByLabel[mock.label] = requiredNetworkMockHitCount(mock);
1269
1373
  }
1270
1374
  checks.push({
1271
1375
  type: "network_mocks_succeeded",
@@ -1276,6 +1380,7 @@ function assessProfile(profile, evidence) {
1276
1380
  required_count: requiredMocks.length,
1277
1381
  hit_count: events.filter((event) => event && event.ok !== false).length,
1278
1382
  hits_by_label: hitsByLabel,
1383
+ required_hits_by_label: requiredHitsByLabel,
1279
1384
  failed,
1280
1385
  },
1281
1386
  message: failed.length ? "Network mocks failed or were not hit for " + failed.length + " mock(s)." : undefined,
@@ -1542,12 +1647,29 @@ function assessProfile(profile, evidence) {
1542
1647
  continue;
1543
1648
  }
1544
1649
  if (check.type === "no_fatal_console_errors") {
1545
- const fatalCount = ((evidence.console && evidence.console.fatal_count) || 0) + ((evidence.page_errors || []).length);
1650
+ const fatalConsoleEvents = ((evidence.console && evidence.console.events) || []).filter((event) => event && (event.type === "error" || event.type === "assert"));
1651
+ const allowedConsoleEvents = fatalConsoleEvents.filter((event) => matchesAllowedMessage(event.text, check.allowed_console_texts, check.allowed_console_patterns));
1652
+ const unallowedConsoleEvents = fatalConsoleEvents.filter((event) => !matchesAllowedMessage(event.text, check.allowed_console_texts, check.allowed_console_patterns));
1653
+ const pageErrors = evidence.page_errors || [];
1654
+ const allowedPageErrors = pageErrors.filter((error) => matchesAllowedMessage(error && error.message, check.allowed_page_error_texts, check.allowed_page_error_patterns));
1655
+ const unallowedPageErrors = pageErrors.filter((error) => !matchesAllowedMessage(error && error.message, check.allowed_page_error_texts, check.allowed_page_error_patterns));
1656
+ const fatalCount = unallowedConsoleEvents.length + unallowedPageErrors.length;
1546
1657
  checks.push({
1547
1658
  type: check.type,
1548
1659
  label: check.label || check.type,
1549
1660
  status: fatalCount ? "failed" : "passed",
1550
- evidence: { console_fatal_count: (evidence.console && evidence.console.fatal_count) || 0, page_error_count: (evidence.page_errors || []).length },
1661
+ evidence: {
1662
+ console_fatal_count: unallowedConsoleEvents.length,
1663
+ page_error_count: unallowedPageErrors.length,
1664
+ total_console_fatal_count: fatalConsoleEvents.length,
1665
+ total_page_error_count: pageErrors.length,
1666
+ allowed_console_fatal_count: allowedConsoleEvents.length,
1667
+ allowed_page_error_count: allowedPageErrors.length,
1668
+ allowed_console_texts: check.allowed_console_texts || [],
1669
+ allowed_console_patterns: check.allowed_console_patterns || [],
1670
+ allowed_page_error_texts: check.allowed_page_error_texts || [],
1671
+ allowed_page_error_patterns: check.allowed_page_error_patterns || [],
1672
+ },
1551
1673
  message: fatalCount ? String(fatalCount) + " fatal browser error(s) were captured." : undefined,
1552
1674
  });
1553
1675
  continue;
@@ -1657,6 +1779,7 @@ async function setupLocatorVisible(locator, index) {
1657
1779
  }
1658
1780
  async function registerNetworkMocks(mocks) {
1659
1781
  for (const mock of mocks || []) {
1782
+ let hitCount = 0;
1660
1783
  await page.route(mock.url, async (route) => {
1661
1784
  const request = route.request();
1662
1785
  const method = request.method ? request.method() : "";
@@ -1665,22 +1788,31 @@ async function registerNetworkMocks(mocks) {
1665
1788
  return;
1666
1789
  }
1667
1790
  try {
1668
- const headers = { ...(mock.headers || {}) };
1669
- let body = mock.body || "";
1670
- let contentType = mock.content_type || headers["content-type"] || headers["Content-Type"] || "text/plain";
1671
- if (mock.body_json !== undefined) {
1672
- body = JSON.stringify(mock.body_json);
1673
- contentType = mock.content_type || headers["content-type"] || headers["Content-Type"] || "application/json";
1791
+ const responses = Array.isArray(mock.responses) ? mock.responses : [];
1792
+ const hitIndex = hitCount;
1793
+ hitCount += 1;
1794
+ const responseIndex = responses.length ? Math.min(hitIndex, responses.length - 1) : null;
1795
+ const response = responseIndex === null ? mock : responses[responseIndex];
1796
+ const headers = { ...(response.headers || mock.headers || {}) };
1797
+ let body = response.body || "";
1798
+ let contentType = response.content_type || headers["content-type"] || headers["Content-Type"] || "text/plain";
1799
+ if (response.body_json !== undefined) {
1800
+ body = JSON.stringify(response.body_json);
1801
+ contentType = response.content_type || headers["content-type"] || headers["Content-Type"] || "application/json";
1674
1802
  }
1675
1803
  networkMockEvents.push({
1676
1804
  ok: true,
1677
1805
  label: mock.label,
1806
+ response_label: response.label || null,
1807
+ hit_index: hitIndex,
1808
+ response_index: responseIndex,
1809
+ sequence_reused: responseIndex !== null && hitIndex >= responses.length,
1678
1810
  url: request.url(),
1679
1811
  method,
1680
- status: mock.status || 200,
1812
+ status: response.status || mock.status || 200,
1681
1813
  });
1682
1814
  await route.fulfill({
1683
- status: mock.status || 200,
1815
+ status: response.status || mock.status || 200,
1684
1816
  headers,
1685
1817
  contentType,
1686
1818
  body,
@@ -34,15 +34,20 @@ interface RiddleProofProfileSetupAction {
34
34
  storage?: "local" | "session" | "both";
35
35
  continue_on_failure?: boolean;
36
36
  }
37
- interface RiddleProofProfileNetworkMock {
38
- label: string;
39
- url: string;
40
- method?: string;
37
+ interface RiddleProofProfileNetworkMockResponse {
38
+ label?: string;
41
39
  status: number;
42
40
  content_type?: string;
43
41
  headers?: Record<string, string>;
44
42
  body?: string;
45
43
  body_json?: JsonValue;
44
+ }
45
+ interface RiddleProofProfileNetworkMock extends RiddleProofProfileNetworkMockResponse {
46
+ label: string;
47
+ url: string;
48
+ method?: string;
49
+ responses?: RiddleProofProfileNetworkMockResponse[];
50
+ required_hit_count?: number;
46
51
  required?: boolean;
47
52
  }
48
53
  interface RiddleProofProfileRouteInventoryRoute {
@@ -77,6 +82,10 @@ interface RiddleProofProfileCheck {
77
82
  text?: string;
78
83
  pattern?: string;
79
84
  flags?: string;
85
+ allowed_console_texts?: string[];
86
+ allowed_console_patterns?: string[];
87
+ allowed_page_error_texts?: string[];
88
+ allowed_page_error_patterns?: string[];
80
89
  min_count?: number;
81
90
  max_overflow_px?: number;
82
91
  timeout_ms?: number;
@@ -250,4 +259,4 @@ declare function buildRiddleProofProfileScript(profile: RiddleProofProfile): str
250
259
  declare function collectRiddleProfileArtifactRefs(input: unknown): RiddleProofProfileArtifactRef[];
251
260
  declare function extractRiddleProofProfileResult(input: unknown): RiddleProofProfileResult | undefined;
252
261
 
253
- export { type NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, type RiddleProofProfile, type RiddleProofProfileArtifactRef, type RiddleProofProfileBaselinePolicy, type RiddleProofProfileBoundsOffender, type RiddleProofProfileCheck, type RiddleProofProfileCheckResult, type RiddleProofProfileCheckType, type RiddleProofProfileEvidence, type RiddleProofProfileFailureAction, type RiddleProofProfileNetworkMock, type RiddleProofProfileResult, type RiddleProofProfileRouteEvidence, type RiddleProofProfileRouteInventoryRoute, type RiddleProofProfileRunner, type RiddleProofProfileSetupAction, type RiddleProofProfileSetupActionType, type RiddleProofProfileStatus, type RiddleProofProfileTarget, type RiddleProofProfileViewport, type RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult };
262
+ export { type NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, type RiddleProofProfile, type RiddleProofProfileArtifactRef, type RiddleProofProfileBaselinePolicy, type RiddleProofProfileBoundsOffender, type RiddleProofProfileCheck, type RiddleProofProfileCheckResult, type RiddleProofProfileCheckType, type RiddleProofProfileEvidence, type RiddleProofProfileFailureAction, type RiddleProofProfileNetworkMock, type RiddleProofProfileNetworkMockResponse, type RiddleProofProfileResult, type RiddleProofProfileRouteEvidence, type RiddleProofProfileRouteInventoryRoute, type RiddleProofProfileRunner, type RiddleProofProfileSetupAction, type RiddleProofProfileSetupActionType, type RiddleProofProfileStatus, type RiddleProofProfileTarget, type RiddleProofProfileViewport, type RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult };
package/dist/profile.d.ts CHANGED
@@ -34,15 +34,20 @@ interface RiddleProofProfileSetupAction {
34
34
  storage?: "local" | "session" | "both";
35
35
  continue_on_failure?: boolean;
36
36
  }
37
- interface RiddleProofProfileNetworkMock {
38
- label: string;
39
- url: string;
40
- method?: string;
37
+ interface RiddleProofProfileNetworkMockResponse {
38
+ label?: string;
41
39
  status: number;
42
40
  content_type?: string;
43
41
  headers?: Record<string, string>;
44
42
  body?: string;
45
43
  body_json?: JsonValue;
44
+ }
45
+ interface RiddleProofProfileNetworkMock extends RiddleProofProfileNetworkMockResponse {
46
+ label: string;
47
+ url: string;
48
+ method?: string;
49
+ responses?: RiddleProofProfileNetworkMockResponse[];
50
+ required_hit_count?: number;
46
51
  required?: boolean;
47
52
  }
48
53
  interface RiddleProofProfileRouteInventoryRoute {
@@ -77,6 +82,10 @@ interface RiddleProofProfileCheck {
77
82
  text?: string;
78
83
  pattern?: string;
79
84
  flags?: string;
85
+ allowed_console_texts?: string[];
86
+ allowed_console_patterns?: string[];
87
+ allowed_page_error_texts?: string[];
88
+ allowed_page_error_patterns?: string[];
80
89
  min_count?: number;
81
90
  max_overflow_px?: number;
82
91
  timeout_ms?: number;
@@ -250,4 +259,4 @@ declare function buildRiddleProofProfileScript(profile: RiddleProofProfile): str
250
259
  declare function collectRiddleProfileArtifactRefs(input: unknown): RiddleProofProfileArtifactRef[];
251
260
  declare function extractRiddleProofProfileResult(input: unknown): RiddleProofProfileResult | undefined;
252
261
 
253
- export { type NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, type RiddleProofProfile, type RiddleProofProfileArtifactRef, type RiddleProofProfileBaselinePolicy, type RiddleProofProfileBoundsOffender, type RiddleProofProfileCheck, type RiddleProofProfileCheckResult, type RiddleProofProfileCheckType, type RiddleProofProfileEvidence, type RiddleProofProfileFailureAction, type RiddleProofProfileNetworkMock, type RiddleProofProfileResult, type RiddleProofProfileRouteEvidence, type RiddleProofProfileRouteInventoryRoute, type RiddleProofProfileRunner, type RiddleProofProfileSetupAction, type RiddleProofProfileSetupActionType, type RiddleProofProfileStatus, type RiddleProofProfileTarget, type RiddleProofProfileViewport, type RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult };
262
+ export { type NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, type RiddleProofProfile, type RiddleProofProfileArtifactRef, type RiddleProofProfileBaselinePolicy, type RiddleProofProfileBoundsOffender, type RiddleProofProfileCheck, type RiddleProofProfileCheckResult, type RiddleProofProfileCheckType, type RiddleProofProfileEvidence, type RiddleProofProfileFailureAction, type RiddleProofProfileNetworkMock, type RiddleProofProfileNetworkMockResponse, type RiddleProofProfileResult, type RiddleProofProfileRouteEvidence, type RiddleProofProfileRouteInventoryRoute, type RiddleProofProfileRunner, type RiddleProofProfileSetupAction, type RiddleProofProfileSetupActionType, type RiddleProofProfileStatus, type RiddleProofProfileTarget, type RiddleProofProfileViewport, type RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult };
package/dist/profile.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  resolveRiddleProofProfileTimeoutSec,
20
20
  slugifyRiddleProofProfileName,
21
21
  summarizeRiddleProofProfileResult
22
- } from "./chunk-ZB7AFRN3.js";
22
+ } from "./chunk-RAVOICNN.js";
23
23
  export {
24
24
  RIDDLE_PROOF_PROFILE_CHECK_TYPES,
25
25
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.7.38",
3
+ "version": "0.7.40",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",