ax-audit 3.6.0 → 4.1.0

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.
Files changed (202) hide show
  1. package/CHANGELOG.md +151 -0
  2. package/LICENSE +1 -1
  3. package/README.md +58 -36
  4. package/dist/baseline.d.ts +2 -0
  5. package/dist/baseline.d.ts.map +1 -1
  6. package/dist/baseline.js +42 -4
  7. package/dist/baseline.js.map +1 -1
  8. package/dist/check-ids.d.ts +19 -0
  9. package/dist/check-ids.d.ts.map +1 -0
  10. package/dist/check-ids.js +53 -0
  11. package/dist/check-ids.js.map +1 -0
  12. package/dist/checks/agent-access.d.ts +23 -6
  13. package/dist/checks/agent-access.d.ts.map +1 -1
  14. package/dist/checks/agent-access.js +200 -54
  15. package/dist/checks/agent-access.js.map +1 -1
  16. package/dist/checks/agent-card.d.ts +37 -0
  17. package/dist/checks/agent-card.d.ts.map +1 -0
  18. package/dist/checks/agent-card.js +352 -0
  19. package/dist/checks/agent-card.js.map +1 -0
  20. package/dist/checks/agent-operability.d.ts +66 -0
  21. package/dist/checks/agent-operability.d.ts.map +1 -0
  22. package/dist/checks/agent-operability.js +383 -0
  23. package/dist/checks/agent-operability.js.map +1 -0
  24. package/dist/checks/agent-skills.d.ts +24 -0
  25. package/dist/checks/agent-skills.d.ts.map +1 -0
  26. package/dist/checks/agent-skills.js +316 -0
  27. package/dist/checks/agent-skills.js.map +1 -0
  28. package/dist/checks/ai-catalog.d.ts +28 -0
  29. package/dist/checks/ai-catalog.d.ts.map +1 -0
  30. package/dist/checks/ai-catalog.js +254 -0
  31. package/dist/checks/ai-catalog.js.map +1 -0
  32. package/dist/checks/ai-directives.d.ts +57 -0
  33. package/dist/checks/ai-directives.d.ts.map +1 -0
  34. package/dist/checks/ai-directives.js +263 -0
  35. package/dist/checks/ai-directives.js.map +1 -0
  36. package/dist/checks/api-discovery.d.ts +26 -0
  37. package/dist/checks/api-discovery.d.ts.map +1 -0
  38. package/dist/checks/api-discovery.js +432 -0
  39. package/dist/checks/api-discovery.js.map +1 -0
  40. package/dist/checks/auth-discovery.d.ts +28 -0
  41. package/dist/checks/auth-discovery.d.ts.map +1 -0
  42. package/dist/checks/auth-discovery.js +213 -0
  43. package/dist/checks/auth-discovery.js.map +1 -0
  44. package/dist/checks/commerce-discovery.d.ts +40 -0
  45. package/dist/checks/commerce-discovery.d.ts.map +1 -0
  46. package/dist/checks/commerce-discovery.js +295 -0
  47. package/dist/checks/commerce-discovery.js.map +1 -0
  48. package/dist/checks/content-negotiation.d.ts.map +1 -1
  49. package/dist/checks/content-negotiation.js +135 -20
  50. package/dist/checks/content-negotiation.js.map +1 -1
  51. package/dist/checks/crawl-efficiency.d.ts +13 -1
  52. package/dist/checks/crawl-efficiency.d.ts.map +1 -1
  53. package/dist/checks/crawl-efficiency.js +65 -1
  54. package/dist/checks/crawl-efficiency.js.map +1 -1
  55. package/dist/checks/frontmatter.d.ts +34 -0
  56. package/dist/checks/frontmatter.d.ts.map +1 -0
  57. package/dist/checks/frontmatter.js +100 -0
  58. package/dist/checks/frontmatter.js.map +1 -0
  59. package/dist/checks/html-rendering.d.ts.map +1 -1
  60. package/dist/checks/html-rendering.js +0 -1
  61. package/dist/checks/html-rendering.js.map +1 -1
  62. package/dist/checks/html-utils.d.ts +10 -0
  63. package/dist/checks/html-utils.d.ts.map +1 -1
  64. package/dist/checks/html-utils.js +19 -0
  65. package/dist/checks/html-utils.js.map +1 -1
  66. package/dist/checks/http-headers.d.ts.map +1 -1
  67. package/dist/checks/http-headers.js +82 -10
  68. package/dist/checks/http-headers.js.map +1 -1
  69. package/dist/checks/http-hygiene.d.ts +26 -0
  70. package/dist/checks/http-hygiene.d.ts.map +1 -0
  71. package/dist/checks/http-hygiene.js +257 -0
  72. package/dist/checks/http-hygiene.js.map +1 -0
  73. package/dist/checks/index.d.ts.map +1 -1
  74. package/dist/checks/index.js +24 -8
  75. package/dist/checks/index.js.map +1 -1
  76. package/dist/checks/llms-txt.d.ts +15 -0
  77. package/dist/checks/llms-txt.d.ts.map +1 -1
  78. package/dist/checks/llms-txt.js +162 -2
  79. package/dist/checks/llms-txt.js.map +1 -1
  80. package/dist/checks/mcp-discovery.d.ts +30 -0
  81. package/dist/checks/mcp-discovery.d.ts.map +1 -0
  82. package/dist/checks/mcp-discovery.js +523 -0
  83. package/dist/checks/mcp-discovery.js.map +1 -0
  84. package/dist/checks/meta-tags.d.ts.map +1 -1
  85. package/dist/checks/meta-tags.js +6 -5
  86. package/dist/checks/meta-tags.js.map +1 -1
  87. package/dist/checks/robots-parser.d.ts +110 -0
  88. package/dist/checks/robots-parser.d.ts.map +1 -0
  89. package/dist/checks/robots-parser.js +277 -0
  90. package/dist/checks/robots-parser.js.map +1 -0
  91. package/dist/checks/robots-txt.d.ts +2 -20
  92. package/dist/checks/robots-txt.d.ts.map +1 -1
  93. package/dist/checks/robots-txt.js +219 -120
  94. package/dist/checks/robots-txt.js.map +1 -1
  95. package/dist/checks/rsl.d.ts +0 -2
  96. package/dist/checks/rsl.d.ts.map +1 -1
  97. package/dist/checks/rsl.js +1 -11
  98. package/dist/checks/rsl.js.map +1 -1
  99. package/dist/checks/security-txt.d.ts.map +1 -1
  100. package/dist/checks/security-txt.js +0 -1
  101. package/dist/checks/security-txt.js.map +1 -1
  102. package/dist/checks/seo-basics.d.ts.map +1 -1
  103. package/dist/checks/seo-basics.js +0 -1
  104. package/dist/checks/seo-basics.js.map +1 -1
  105. package/dist/checks/sitemap.d.ts.map +1 -1
  106. package/dist/checks/sitemap.js +0 -1
  107. package/dist/checks/sitemap.js.map +1 -1
  108. package/dist/checks/structured-data.d.ts.map +1 -1
  109. package/dist/checks/structured-data.js +215 -4
  110. package/dist/checks/structured-data.js.map +1 -1
  111. package/dist/checks/structured-fields.d.ts +46 -0
  112. package/dist/checks/structured-fields.d.ts.map +1 -0
  113. package/dist/checks/structured-fields.js +112 -0
  114. package/dist/checks/structured-fields.js.map +1 -0
  115. package/dist/checks/surface.d.ts +59 -0
  116. package/dist/checks/surface.d.ts.map +1 -0
  117. package/dist/checks/surface.js +106 -0
  118. package/dist/checks/surface.js.map +1 -0
  119. package/dist/checks/tls-https.d.ts.map +1 -1
  120. package/dist/checks/tls-https.js +0 -1
  121. package/dist/checks/tls-https.js.map +1 -1
  122. package/dist/checks/usage-policy.d.ts +53 -0
  123. package/dist/checks/usage-policy.d.ts.map +1 -0
  124. package/dist/checks/usage-policy.js +339 -0
  125. package/dist/checks/usage-policy.js.map +1 -0
  126. package/dist/checks/utils.d.ts +25 -1
  127. package/dist/checks/utils.d.ts.map +1 -1
  128. package/dist/checks/utils.js +33 -1
  129. package/dist/checks/utils.js.map +1 -1
  130. package/dist/checks/waf.d.ts +75 -0
  131. package/dist/checks/waf.d.ts.map +1 -0
  132. package/dist/checks/waf.js +203 -0
  133. package/dist/checks/waf.js.map +1 -0
  134. package/dist/checks/webmcp.d.ts +55 -0
  135. package/dist/checks/webmcp.d.ts.map +1 -0
  136. package/dist/checks/webmcp.js +209 -0
  137. package/dist/checks/webmcp.js.map +1 -0
  138. package/dist/checks/well-known.d.ts +38 -0
  139. package/dist/checks/well-known.d.ts.map +1 -0
  140. package/dist/checks/well-known.js +202 -0
  141. package/dist/checks/well-known.js.map +1 -0
  142. package/dist/cli.d.ts +12 -0
  143. package/dist/cli.d.ts.map +1 -1
  144. package/dist/cli.js +110 -4
  145. package/dist/cli.js.map +1 -1
  146. package/dist/constants.d.ts +195 -14
  147. package/dist/constants.d.ts.map +1 -1
  148. package/dist/constants.js +598 -70
  149. package/dist/constants.js.map +1 -1
  150. package/dist/fetcher.d.ts.map +1 -1
  151. package/dist/fetcher.js +44 -14
  152. package/dist/fetcher.js.map +1 -1
  153. package/dist/guide-urls.js +1 -1
  154. package/dist/guide-urls.js.map +1 -1
  155. package/dist/index.d.ts +22 -2
  156. package/dist/index.d.ts.map +1 -1
  157. package/dist/index.js +20 -1
  158. package/dist/index.js.map +1 -1
  159. package/dist/orchestrator.d.ts.map +1 -1
  160. package/dist/orchestrator.js +5 -1
  161. package/dist/orchestrator.js.map +1 -1
  162. package/dist/reporter/html.d.ts +9 -0
  163. package/dist/reporter/html.d.ts.map +1 -1
  164. package/dist/reporter/html.js +49 -11
  165. package/dist/reporter/html.js.map +1 -1
  166. package/dist/reporter/markdown.d.ts.map +1 -1
  167. package/dist/reporter/markdown.js +36 -6
  168. package/dist/reporter/markdown.js.map +1 -1
  169. package/dist/reporter/terminal.d.ts.map +1 -1
  170. package/dist/reporter/terminal.js +36 -1
  171. package/dist/reporter/terminal.js.map +1 -1
  172. package/dist/scorer.d.ts +24 -1
  173. package/dist/scorer.d.ts.map +1 -1
  174. package/dist/scorer.js +51 -6
  175. package/dist/scorer.js.map +1 -1
  176. package/dist/types.d.ts +90 -3
  177. package/dist/types.d.ts.map +1 -1
  178. package/docs/api.md +58 -2
  179. package/docs/architecture.md +27 -11
  180. package/docs/checks.md +285 -52
  181. package/docs/cli.md +36 -0
  182. package/docs/concepts.md +27 -13
  183. package/docs/faq.md +18 -6
  184. package/docs/getting-started.md +20 -13
  185. package/docs/roadmap.md +367 -0
  186. package/package.json +13 -5
  187. package/dist/checks/agent-json.d.ts +0 -14
  188. package/dist/checks/agent-json.d.ts.map +0 -1
  189. package/dist/checks/agent-json.js +0 -167
  190. package/dist/checks/agent-json.js.map +0 -1
  191. package/dist/checks/mcp.d.ts +0 -4
  192. package/dist/checks/mcp.d.ts.map +0 -1
  193. package/dist/checks/mcp.js +0 -162
  194. package/dist/checks/mcp.js.map +0 -1
  195. package/dist/checks/openapi.d.ts +0 -4
  196. package/dist/checks/openapi.d.ts.map +0 -1
  197. package/dist/checks/openapi.js +0 -121
  198. package/dist/checks/openapi.js.map +0 -1
  199. package/dist/checks/well-known-ai.d.ts +0 -17
  200. package/dist/checks/well-known-ai.d.ts.map +0 -1
  201. package/dist/checks/well-known-ai.js +0 -123
  202. package/dist/checks/well-known-ai.js.map +0 -1
@@ -1,5 +1,18 @@
1
1
  import chalk from 'chalk';
2
2
  import { getGrade } from '../scorer.js';
3
+ import { CHECK_CATEGORIES } from '../constants.js';
4
+ /** Display order and headings for grouped output. */
5
+ const CATEGORY_ORDER = ['content', 'discovery', 'access', 'policy', 'protocols'];
6
+ const CATEGORY_HEADING = {
7
+ content: 'Content — is there substance an agent can read?',
8
+ discovery: 'Discovery — can an agent find your machine-readable files?',
9
+ access: 'Access — can an agent actually retrieve them?',
10
+ policy: 'Policy — what usage rights do you declare?',
11
+ protocols: 'Protocols — what can an agent call?',
12
+ };
13
+ function categoryOf(check) {
14
+ return check.category ?? CHECK_CATEGORIES[check.id] ?? 'discovery';
15
+ }
3
16
  const STATUS_ICONS = {
4
17
  pass: chalk.green(' PASS '),
5
18
  warn: chalk.yellow(' WARN '),
@@ -33,6 +46,10 @@ export function reportTerminal(report, diff) {
33
46
  console.log(chalk.dim(` ${report.timestamp} (${report.duration}ms)`));
34
47
  if (diff) {
35
48
  console.log(chalk.dim(` Baseline: ${diff.baselineTimestamp}`));
49
+ if (diff.scoringModelChanged) {
50
+ console.log(chalk.yellow(' Baseline predates this scoring model — deltas measure the model change as much as the site.'));
51
+ console.log(chalk.dim(' Regression gating is suspended. Re-save with --save-baseline to resume it.'));
52
+ }
36
53
  }
37
54
  console.log();
38
55
  const barWidth = 40;
@@ -48,9 +65,27 @@ export function reportTerminal(report, diff) {
48
65
  checkDiffs.set(cd.id, cd);
49
66
  }
50
67
  }
68
+ // Group by category so a reader sees which *area* is weak, not a flat list of
69
+ // twenty scores. Categories with no checks in this run are skipped.
70
+ const byCategory = new Map();
51
71
  for (const check of report.results) {
72
+ const category = categoryOf(check);
73
+ byCategory.set(category, [...(byCategory.get(category) ?? []), check]);
74
+ }
75
+ const ordered = CATEGORY_ORDER.filter((c) => byCategory.has(c)).flatMap((category) => [
76
+ { heading: CATEGORY_HEADING[category] },
77
+ ...byCategory.get(category).map((check) => ({ check })),
78
+ ]);
79
+ for (const entry of ordered) {
80
+ if ('heading' in entry) {
81
+ console.log(chalk.dim(` ── ${entry.heading}`));
82
+ console.log();
83
+ continue;
84
+ }
85
+ const check = entry.check;
52
86
  const cd = checkDiffs.get(check.id);
53
- const header = chalk.bold(` ${check.name}`) + chalk.dim(` (${check.score}/100)`);
87
+ const header = chalk.bold(` ${check.name}`) +
88
+ (check.applicable === false ? chalk.dim(' (n/a)') : chalk.dim(` (${check.score}/100)`));
54
89
  console.log(cd ? header + formatDelta(cd.delta) : header);
55
90
  for (const finding of check.findings) {
56
91
  console.log(`${STATUS_ICONS[finding.status]} ${finding.message}`);
@@ -1 +1 @@
1
- {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/reporter/terminal.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/reporter/terminal.ts"],"names":[],"mappings":"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"}
package/dist/scorer.d.ts CHANGED
@@ -1,4 +1,27 @@
1
- import type { CheckResult, CheckMeta, Grade } from './types.js';
1
+ import type { CheckCategory, CheckResult, CheckMeta, Grade } from './types.js';
2
+ /**
3
+ * Weighted average across the checks that ran and apply.
4
+ *
5
+ * A check that reports `applicable: false` is excluded from both the numerator
6
+ * and the denominator. Scoring a commerce-protocol check as zero on a personal
7
+ * blog would say the blog is badly built, when the honest answer is that the
8
+ * question does not arise. That distinction is what makes a low score
9
+ * actionable: everything counted against a site is something the site could
10
+ * have done.
11
+ */
2
12
  export declare function calculateOverallScore(results: CheckResult[], metas: CheckMeta[]): number;
3
13
  export declare function getGrade(score: number): Grade;
14
+ /**
15
+ * Score of one report area, over the checks in it that apply.
16
+ *
17
+ * `null` when the area has nothing applicable — a site with no protocol
18
+ * surface at all has no protocols score, and reporting 0 there would say
19
+ * the opposite of what the N/A results say individually.
20
+ *
21
+ * An overall number hides an area that is entirely broken: a site can
22
+ * score 80 while every access check fails, because the other four areas
23
+ * carry it. This is what `--fail-on-category` gates on, and what a report
24
+ * grouped by area shows per group.
25
+ */
26
+ export declare function categoryScore(results: CheckResult[], category: CheckCategory): number | null;
4
27
  //# sourceMappingURL=scorer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scorer.d.ts","sourceRoot":"","sources":["../src/scorer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEhE,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,CAwBxF;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAK7C"}
1
+ {"version":3,"file":"scorer.d.ts","sourceRoot":"","sources":["../src/scorer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAE/E;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,CA+BxF;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAK7C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAe5F"}
package/dist/scorer.js CHANGED
@@ -1,22 +1,40 @@
1
- import { CHECK_WEIGHTS, GRADES } from './constants.js';
1
+ import { CHECK_CATEGORIES, CHECK_WEIGHTS, GRADES } from './constants.js';
2
+ import { checks as allChecks } from './checks/index.js';
2
3
  import { clampScore } from './checks/utils.js';
4
+ /**
5
+ * Weighted average across the checks that ran and apply.
6
+ *
7
+ * A check that reports `applicable: false` is excluded from both the numerator
8
+ * and the denominator. Scoring a commerce-protocol check as zero on a personal
9
+ * blog would say the blog is badly built, when the honest answer is that the
10
+ * question does not arise. That distinction is what makes a low score
11
+ * actionable: everything counted against a site is something the site could
12
+ * have done.
13
+ */
3
14
  export function calculateOverallScore(results, metas) {
15
+ const applicable = results.filter((r) => r.applicable !== false);
16
+ const applicableIds = new Set(applicable.map((r) => r.id));
4
17
  const weightMap = {};
5
18
  let totalWeight = 0;
6
19
  for (const m of metas) {
7
20
  weightMap[m.id] = m.weight ?? CHECK_WEIGHTS[m.id] ?? 10;
21
+ // A meta with no corresponding result (the check crashed before producing
22
+ // one) still counts, so a broken check cannot inflate a score by shrinking
23
+ // the denominator. Only an explicit not-applicable result is excluded.
24
+ if (results.some((r) => r.id === m.id) && !applicableIds.has(m.id))
25
+ continue;
8
26
  totalWeight += weightMap[m.id];
9
27
  }
10
- // All selected checks are informational (weight 0) — e.g. `--checks content-negotiation`.
28
+ // Every applicable check is informational (weight 0) — e.g. `--checks content-negotiation`.
11
29
  // Fall back to a plain average instead of dividing by zero.
12
30
  if (totalWeight === 0) {
13
- if (results.length === 0)
31
+ if (applicable.length === 0)
14
32
  return 0;
15
- const sum = results.reduce((acc, r) => acc + r.score, 0);
16
- return clampScore(Math.round(sum / results.length));
33
+ const sum = applicable.reduce((acc, r) => acc + r.score, 0);
34
+ return clampScore(Math.round(sum / applicable.length));
17
35
  }
18
36
  let weightedSum = 0;
19
- for (const r of results) {
37
+ for (const r of applicable) {
20
38
  const weight = weightMap[r.id] ?? 0;
21
39
  weightedSum += (r.score / 100) * weight;
22
40
  }
@@ -29,4 +47,31 @@ export function getGrade(score) {
29
47
  }
30
48
  return GRADES[GRADES.length - 1];
31
49
  }
50
+ /**
51
+ * Score of one report area, over the checks in it that apply.
52
+ *
53
+ * `null` when the area has nothing applicable — a site with no protocol
54
+ * surface at all has no protocols score, and reporting 0 there would say
55
+ * the opposite of what the N/A results say individually.
56
+ *
57
+ * An overall number hides an area that is entirely broken: a site can
58
+ * score 80 while every access check fails, because the other four areas
59
+ * carry it. This is what `--fail-on-category` gates on, and what a report
60
+ * grouped by area shows per group.
61
+ */
62
+ export function categoryScore(results, category) {
63
+ const metas = new Map(allChecks.map((c) => [c.meta.id, c.meta]));
64
+ const inCategory = results.filter((r) => {
65
+ if (r.applicable === false)
66
+ return false;
67
+ const meta = metas.get(r.id);
68
+ return (meta?.category ?? CHECK_CATEGORIES[r.id]) === category;
69
+ });
70
+ if (inCategory.length === 0)
71
+ return null;
72
+ const metasFor = inCategory
73
+ .map((r) => metas.get(r.id))
74
+ .filter((m) => m !== undefined);
75
+ return calculateOverallScore(inCategory, metasFor);
76
+ }
32
77
  //# sourceMappingURL=scorer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scorer.js","sourceRoot":"","sources":["../src/scorer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,MAAM,UAAU,qBAAqB,CAAC,OAAsB,EAAE,KAAkB;IAC9E,MAAM,SAAS,GAA2B,EAAE,CAAC;IAC7C,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QACxD,WAAW,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,0FAA0F;IAC1F,4DAA4D;IAC5D,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;QACtB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QACnC,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACzD,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QACpC,WAAW,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC;IAC1C,CAAC;IAED,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,IAAI,KAAK,CAAC,GAAG;YAAE,OAAO,KAAK,CAAC;IACvC,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACnC,CAAC"}
1
+ {"version":3,"file":"scorer.js","sourceRoot":"","sources":["../src/scorer.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -13,12 +13,46 @@ export interface CheckResult {
13
13
  score: number;
14
14
  findings: Finding[];
15
15
  duration: number;
16
- }
16
+ /**
17
+ * `false` when the check does not apply to this site (no API surface for
18
+ * `api-discovery`, no commerce signals for `commerce-discovery`, ...).
19
+ * Not-applicable checks are reported as N/A and excluded from the weighted
20
+ * denominator instead of scoring 0. Absent means applicable.
21
+ */
22
+ applicable?: boolean;
23
+ /** Category used to group results in reports. Mirrors `CheckMeta.category`. */
24
+ category?: CheckCategory;
25
+ }
26
+ /**
27
+ * Report grouping for a check. Categories describe *what kind of readiness*
28
+ * a check measures, so reports can summarise per area rather than as one
29
+ * undifferentiated list of 20+ checks.
30
+ *
31
+ * - `content` — is there substance an agent can read and quote?
32
+ * - `discovery` — can an agent find the site's machine-readable entry points?
33
+ * - `access` — can an agent actually retrieve it (crawler policy, WAFs, HTTP hygiene)?
34
+ * - `policy` — what are the declared usage rights, and are they consistent?
35
+ * - `protocols` — callable surfaces: A2A, MCP, OpenAPI, skills, commerce.
36
+ */
37
+ export type CheckCategory = 'content' | 'discovery' | 'access' | 'policy' | 'protocols';
17
38
  export interface CheckMeta {
18
39
  id: string;
19
40
  name: string;
20
41
  description: string;
21
- weight: number;
42
+ /**
43
+ * Optional per-check override. Weights normally live in one place,
44
+ * `CHECK_WEIGHTS`; declaring them here as well let the two drift apart, which
45
+ * is exactly what happened between 3.x and 4.0. Prefer the central map.
46
+ */
47
+ weight?: number;
48
+ /** Report grouping. Falls back to `CHECK_CATEGORIES[id]` when omitted. */
49
+ category?: CheckCategory;
50
+ /**
51
+ * Former ids for this check. `--checks` selection and baseline diffing
52
+ * resolve aliases, so renaming a check never silently drops a saved
53
+ * baseline entry or breaks an existing CI invocation.
54
+ */
55
+ aliases?: string[];
22
56
  }
23
57
  export interface FetchResponse {
24
58
  status: number;
@@ -27,6 +61,12 @@ export interface FetchResponse {
27
61
  ok: boolean;
28
62
  url: string;
29
63
  error?: string;
64
+ /** Wall-clock duration of the request in milliseconds (undefined for synthetic responses). */
65
+ elapsedMs?: number;
66
+ /** Whether the fetch followed at least one redirect before producing this response. */
67
+ redirected?: boolean;
68
+ /** `Location` header value when the request was made with `redirect: 'manual'` and got a 3xx. */
69
+ redirectLocation?: string;
30
70
  }
31
71
  /** Per-request options for the audit fetcher. */
32
72
  export interface FetchOptions {
@@ -36,12 +76,30 @@ export interface FetchOptions {
36
76
  * the default one. Header names are case-insensitive.
37
77
  */
38
78
  headers?: Record<string, string>;
79
+ /**
80
+ * HTTP method. `HEAD` is used for cheap liveness probes (llms.txt link
81
+ * sampling, catalog entry resolution) where the body is irrelevant.
82
+ * Default `GET`.
83
+ */
84
+ method?: 'GET' | 'HEAD';
85
+ /**
86
+ * Redirect handling. `manual` returns the 3xx response itself with
87
+ * `redirectLocation` populated, so checks can count hops and inspect
88
+ * redirect targets. Default `follow`.
89
+ */
90
+ redirect?: 'follow' | 'manual';
39
91
  }
40
92
  export interface CheckContext {
41
93
  url: string;
42
94
  fetch: (url: string, options?: FetchOptions) => Promise<FetchResponse>;
43
95
  html: string;
44
96
  headers: Record<string, string>;
97
+ /**
98
+ * Forces protocol checks applicable regardless of what the site currently
99
+ * exposes, so a team can audit against what they intend to build. `auto`
100
+ * (the default) detects each surface from the site itself.
101
+ */
102
+ profile?: 'auto' | 'api' | 'mcp' | 'agent' | 'docs' | 'commerce' | 'all';
45
103
  }
46
104
  export interface CheckModule {
47
105
  run: (ctx: CheckContext) => Promise<CheckResult>;
@@ -63,6 +121,12 @@ export interface AuditReport {
63
121
  export interface AuditOptions {
64
122
  url: string;
65
123
  checks?: string[];
124
+ /**
125
+ * Forces protocol checks applicable. By default a check for a surface the
126
+ * site does not have reports N/A rather than zero; a profile says "audit me
127
+ * as though I had one".
128
+ */
129
+ profile?: 'auto' | 'api' | 'mcp' | 'agent' | 'docs' | 'commerce' | 'all';
66
130
  timeout?: number;
67
131
  verbose?: boolean;
68
132
  /** Retry attempts for transient fetch failures (timeouts, 5xx, network errors). Default 2. */
@@ -89,12 +153,24 @@ export interface SecurityHeader {
89
153
  critical: boolean;
90
154
  }
91
155
  export type OutputFormat = 'terminal' | 'json' | 'html' | 'markdown';
92
- /** Minimal snapshot of an audit run stored as the baseline file. */
156
+ /**
157
+ * Minimal snapshot of an audit run stored as the baseline file.
158
+ *
159
+ * `schemaVersion` records which scoring model produced it. A baseline written
160
+ * before 4.0 was scored under different weights and without not-applicable
161
+ * exclusion, so comparing it directly to a 4.0 run reports regressions the
162
+ * site did not cause. Version 1 baselines (no field) are still read, and the
163
+ * diff says the comparison spans a scoring change.
164
+ */
93
165
  export interface BaselineData {
166
+ /** Absent on baselines written before 4.0, which are treated as version 1. */
167
+ schemaVersion?: number;
94
168
  url: string;
95
169
  timestamp: string;
96
170
  overallScore: number;
97
171
  checks: Record<string, number>;
172
+ /** Check ids that reported N/A, so a later N/A is not read as a change. */
173
+ notApplicable?: string[];
98
174
  }
99
175
  /** Per-check score delta. */
100
176
  export interface CheckDiff {
@@ -103,9 +179,20 @@ export interface CheckDiff {
103
179
  previous: number;
104
180
  current: number;
105
181
  delta: number;
182
+ /**
183
+ * True when this check is N/A on one side of the comparison, so the delta is
184
+ * a change of applicability rather than of quality. Excluded from
185
+ * regressions.
186
+ */
187
+ applicabilityChanged?: boolean;
106
188
  }
107
189
  /** Full diff between the current audit and a stored baseline. */
108
190
  export interface BaselineDiff {
191
+ /**
192
+ * Set when the baseline predates the current scoring model. Deltas are still
193
+ * shown, but they measure the model change as much as the site.
194
+ */
195
+ scoringModelChanged?: boolean;
109
196
  url: string;
110
197
  baselineTimestamp: string;
111
198
  currentTimestamp: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/docs/api.md CHANGED
@@ -105,6 +105,12 @@ function getGrade(score: number): Grade;
105
105
 
106
106
  `calculateOverallScore` computes the weighted average; it falls back to a plain average when all selected checks have weight 0, and returns 0 for empty input. `getGrade` maps a score to its `Grade`.
107
107
 
108
+ ```ts
109
+ function categoryScore(results: CheckResult[], category: CheckCategory): number | null;
110
+ ```
111
+
112
+ `categoryScore` is the same arithmetic over one area, and `null` when the area has nothing applicable. An overall number hides an area that is entirely broken — a site can score 80 while every access check fails, because the other four carry it. This is what `--fail-on-category` gates on and what a report grouped by area shows per group.
113
+
108
114
  ## Baselines
109
115
 
110
116
  ```typescript
@@ -187,12 +193,62 @@ interface FetchResponse {
187
193
 
188
194
  `ctx.fetch` custom headers merge case-insensitively over the defaults (a custom `Accept` or `User-Agent` replaces the default), and responses are cached per URL + normalized headers — mirroring HTTP `Vary`. Your `fetch` implementation should never throw; model failures as `{ status: 0, ok: false, error }`.
189
195
 
196
+ ## Reference tables
197
+
198
+ Exported so a consumer can *describe* an audit rather than only run one:
199
+ a report that prints what a check is worth, a page that groups results by
200
+ area, a robots.txt editor that names the crawlers worth naming. Before
201
+ 4.1 none of these were reachable — the `exports` map admits only the
202
+ entry point — so every consumer transcribed them and wrote a test to
203
+ catch the day the copy went stale.
204
+
205
+ ```ts
206
+ const VERSION: string;
207
+
208
+ const CHECK_WEIGHTS: Record<string, number>;
209
+ const CHECK_CATEGORIES: Record<string, CheckCategory>;
210
+ const GRADES: Grade[];
211
+
212
+ const AI_CRAWLERS: Record<CrawlerPurpose, string[]>;
213
+ const ALL_AI_CRAWLERS: string[];
214
+ const CORE_AI_CRAWLERS: string[];
215
+ const LEGACY_AI_CRAWLERS: Record<string, string>; // token -> why it does nothing
216
+ const CRAWLER_META: Record<string, CrawlerInfo>;
217
+ const CONTENT_SIGNALS: string[];
218
+
219
+ function crawlerInfo(token: string): CrawlerInfo | undefined;
220
+ function crawlerPurpose(token: string): CrawlerPurpose | undefined;
221
+ function legacyCrawlerNote(token: string): string | undefined;
222
+
223
+ type CrawlerPurpose = 'training' | 'search' | 'user-fetch' | 'agent';
224
+
225
+ interface CrawlerInfo {
226
+ vendor: string;
227
+ purpose: CrawlerPurpose;
228
+ honorsRobots: boolean | 'partial';
229
+ impact: string; // one sentence on what blocking this costs
230
+ docUrl: string;
231
+ ipListUrl?: string; // published ranges, for reverse verification
232
+ signsRequests?: boolean; // Web Bot Auth (RFC 9421)
233
+ tokenOnly?: boolean; // a robots.txt control that never appears in a request
234
+ note?: string;
235
+ }
236
+ ```
237
+
238
+ `CHECK_WEIGHTS` and `CHECK_CATEGORIES` both cover every shipped check, and
239
+ `test/public-api.test.js` fails if either stops doing so. A check may also
240
+ declare `meta.category` for itself; when it does, the two must agree.
241
+
242
+ The rest of `constants.ts` — thresholds, media types, required-field
243
+ lists — stays private. A consumer pinned to those would make every
244
+ check's internals a breaking change.
245
+
190
246
  ## API stability
191
247
 
192
248
  Within a major version, the exported function signatures and the `AuditReport` JSON shape are stable. Specifically:
193
249
 
194
- - **Stable:** `audit`, `batchAudit`, `calculateOverallScore`, `getGrade`, the baseline functions, the reporter functions, and all exported type *shapes*.
195
- - **May change in minor versions:** the *set* of checks (new checks are added), individual check `score`/`findings` content, and check `weight` values (new checks start at 0; reweighting is reserved for majors). Treat `results` as a list to iterate, not a fixed-length tuple.
250
+ - **Stable:** `audit`, `batchAudit`, `calculateOverallScore`, `categoryScore`, `getGrade`, the baseline functions, the reporter functions, the reference tables above, and all exported type *shapes*.
251
+ - **May change in minor versions:** the *set* of checks (new checks are added), individual check `score`/`findings` content, check `weight` values (new checks start at 0; reweighting is reserved for majors), and the *contents* of the reference tables — a crawler token is added the week its vendor documents one, and waiting for a major would make the table wrong for months. The tables themselves, and their shapes, are stable. Treat `results` as a list to iterate, not a fixed-length tuple.
196
252
  - **Internal:** anything not exported from `src/index.ts`, including terminal/HTML reporters and individual check modules' internals.
197
253
 
198
254
  ## Exported types
@@ -17,9 +17,9 @@ cli.ts ──► orchestrator.ts ──► checks/* (Promise.allSettled, paralle
17
17
  1. **cli.ts** parses and validates flags, loads the baseline if requested, and dispatches to single or batch mode.
18
18
  2. **orchestrator.ts** (`audit`) creates one fetcher per run, fetches the homepage once, builds the `CheckContext` (`url`, `html`, `headers`, `fetch`), and runs all selected checks in parallel. A check that throws is converted into a score-0 result with the error as a finding — one bad check never kills the audit. `batchAudit` runs `audit` per URL through an order-preserving work queue with configurable `concurrency`.
19
19
  3. **fetcher.ts** wraps `fetch` with: per-run in-memory caching keyed on URL + normalized (lowercased, sorted) custom headers — mirroring HTTP `Vary` semantics so a `text/markdown` probe never collides with the HTML fetch; case-insensitive header merging over defaults; timeouts via `AbortController`; and retries with exponential backoff for transient failures (status 0, 408, 425, 429, 5xx). Errors never throw — they become `{ status: 0, ok: false, error }` results, also cached.
20
- 4. **checks/** — one module per check (18). Each exports `default` (async check function) and `meta` (`{ id, name, description, weight }`).
21
- 5. **scorer.ts** computes the weighted average; when all selected checks have weight 0 it falls back to a plain average.
22
- 6. **reporter/** renders to terminal (chalk), JSON, self-contained HTML, or Markdown.
20
+ 4. **checks/** — one module per check (26). Each exports `default` (async check function) and `meta` (`{ id, name, description, weight, category?, aliases? }`).
21
+ 5. **scorer.ts** computes the weighted average over the checks that ran *and apply*; a check reporting `applicable: false` is excluded from both numerator and denominator. When every applicable check has weight 0 it falls back to a plain average.
22
+ 6. **reporter/** renders to terminal (chalk), JSON, self-contained HTML, or Markdown, grouping checks by category and showing n/a where a check does not apply.
23
23
  7. **baseline.ts** persists minimal score snapshots and computes per-check diffs for regression gating.
24
24
 
25
25
  ## Anatomy of a check
@@ -33,7 +33,8 @@ export const meta: CheckMeta = {
33
33
  id: 'my-check',
34
34
  name: 'My Check',
35
35
  description: 'One-line description shown in reports',
36
- weight: 0, // new checks start informational in 3.x
36
+ category: 'discovery',
37
+ // No `weight` here: weights live in CHECK_WEIGHTS, and only there.
37
38
  };
38
39
 
39
40
  export default async function check(ctx: CheckContext): Promise<CheckResult> {
@@ -60,9 +61,15 @@ export default async function check(ctx: CheckContext): Promise<CheckResult> {
60
61
 
61
62
  Conventions:
62
63
 
63
- - **Findings are actionable.** Every `warn`/`fail` carries a `hint` with concrete remediation and a `learnMoreUrl` pointing to `lucioduran.com/projects/ax-audit/guides/<check-id>#<anchor>`. Every anchor must have a section in that guide.
64
+ - **Findings are actionable.** Every `warn`/`fail` carries a `hint` with concrete remediation and a `learnMoreUrl` pointing to `axrush.com/guides/<check-id>#<anchor>`. Every anchor must have a section in that guide.
64
65
  - **Scores are clamped** to [0, 100] by `buildResult`.
65
66
  - **Shared HTML primitives** live in `checks/html-utils.ts` (`getMetaContent`, `findLinkTags`, `getAttribute`, `extractVisibleText`, …) — no per-check regex duplication.
67
+ - **robots.txt is parsed once**, by `checks/robots-parser.ts`. It returns User-agent groups with their rules plus `Content-Signal`, `Content-Usage`, `License`, `Sitemap` and `Agentmap` directives. `robots-txt`, `rsl` and `agent-access` all consume it, so the grouping rules have one definition.
68
+ - **Responses are classified**, not just status-checked. `checks/waf.ts` turns a response into ok / challenge / paywall / needs-signature / license-required / rate-limited / blocked, with the evidence that produced it and an `inconclusive` flag for what an unsigned probe cannot settle.
69
+ - **Probed paths carry their standing.** `checks/well-known.ts` records every path as IANA-registered, vendor convention, draft or legacy, so a missing draft file is never reported like a missing registered one.
70
+ - **An HTML body means absent, not broken.** `isHtmlDocument` in `checks/utils.ts` gates speculative probes: an SPA catch-all returns its index shell for every unknown path, and reporting that as a malformed document sends operators hunting for a bug in a file they never wrote.
71
+ - **A check that does not apply reports N/A**, via `notApplicable()`, rather than scoring 0. Commerce discovery on a blog, OAuth metadata where nothing needs authorizing, WebMCP on a page with no forms: scoring these zero would say something false about the site. Everything counted against a site must be something the site could have done.
72
+ - **Check ids are a public interface** — they appear in `--checks` flags and in saved baselines. A rename declares the old id in `meta.aliases`; `src/check-ids.ts` resolves aliases for selection and for baseline diffing.
66
73
  - **Content-Type validation** uses `checkContentType` from `checks/utils.ts` (−5 convention for mismatches).
67
74
  - **Network goes through `ctx.fetch`** — never raw `fetch` — so caching, retries, timeouts, and `--verbose` logging apply uniformly.
68
75
 
@@ -75,14 +82,23 @@ Conventions:
75
82
  5. Document it in `docs/checks.md` and the README table.
76
83
  6. Write the remediation guide covering every `learnMoreUrl` anchor you emit.
77
84
 
78
- ## Scoring policy (3.x)
85
+ ## Scoring policy
79
86
 
80
- Score deltas on the same site are treated as **breaking** (see CHANGELOG 3.0.0). Therefore in 3.x:
87
+ Score deltas on the same site are treated as **breaking**. Within a major version:
81
88
 
82
- - New checks ship with **weight 0** (informational): full findings, no effect on the overall score or baselines.
83
- - New findings inside weighted checks must be informational (no score deduction) — see the Content Signals findings in `robots-txt`.
84
- - Weight redistribution happens in major versions (v4.0).
89
+ - New checks ship with **weight 0**: full findings, no effect on the overall score or baselines.
90
+ - New findings inside weighted checks must be informational, with no deduction.
91
+ - Weight redistribution happens in a major version, and the baseline schema version is bumped with it so an existing baseline is not read as a regression.
92
+
93
+ Weights live in `CHECK_WEIGHTS` in `src/constants.ts`, and only there. Checks used to declare their own `meta.weight` alongside the map; the two drifted, and a redistribution silently did nothing. `CheckMeta.weight` remains as an override that nothing uses, and a test asserts no check declares one.
94
+
95
+ Two check states exist beyond a score:
96
+
97
+ - **Weight 0** means the check runs and reports but rests on something too unsettled to score: a draft specification that may be renamed.
98
+ - **Not applicable** means the question does not arise for this site. It leaves the denominator entirely. `--profile` overrides the detection.
85
99
 
86
100
  ## Testing
87
101
 
88
- `npm test` builds (`tsc`) and runs `node --test`. The suite (301 tests) covers every check, the scorer, baseline logic, the Markdown reporter, plus integration tests that spin up real local HTTP servers for the fetcher (per-header caching, retries) and the batch orchestrator (ordering, concurrency caps). No test dependencies beyond Node.
102
+ `npm test` builds (`tsc`) and runs `node --test`. The suite (964 tests) covers every check, the scorer, baseline logic, the Markdown reporter, plus integration tests that spin up real local HTTP servers for the fetcher (per-header caching, retries, HEAD and manual redirects) and the batch orchestrator (ordering, concurrency caps). No test dependencies beyond Node.
103
+
104
+ Two classes of test exist specifically to keep the 3.x promise that no score goes down: **score-stability tests** assert that a configuration which scored 100 in 3.6 still scores 100, and that findings added inside a weighted check leave the score untouched. When those fail, the change belongs in the next major, not the current minor.