ssrwire 0.2.0 → 0.4.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.
- package/CHANGELOG.md +47 -1
- package/CONTRIBUTING.md +3 -1
- package/PUBLISHING.md +15 -15
- package/README.md +179 -29
- package/dist/analyze.d.ts.map +1 -1
- package/dist/analyze.js +162 -6
- package/dist/analyze.js.map +1 -1
- package/dist/audit-report.d.ts +8 -0
- package/dist/audit-report.d.ts.map +1 -0
- package/dist/audit-report.js +243 -0
- package/dist/audit-report.js.map +1 -0
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js +2 -0
- package/dist/audit.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +77 -10
- package/dist/cli.js.map +1 -1
- package/dist/compare.d.ts +6 -0
- package/dist/compare.d.ts.map +1 -0
- package/dist/compare.js +720 -0
- package/dist/compare.js.map +1 -0
- package/dist/comparison-reporters.d.ts +9 -0
- package/dist/comparison-reporters.d.ts.map +1 -0
- package/dist/comparison-reporters.js +223 -0
- package/dist/comparison-reporters.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +20 -1
- package/dist/config.js.map +1 -1
- package/dist/http-probe.d.ts.map +1 -1
- package/dist/http-probe.js +4 -0
- package/dist/http-probe.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/redact.d.ts.map +1 -1
- package/dist/redact.js +6 -0
- package/dist/redact.js.map +1 -1
- package/dist/reporters.d.ts.map +1 -1
- package/dist/reporters.js +27 -0
- package/dist/reporters.js.map +1 -1
- package/dist/social.d.ts +14 -0
- package/dist/social.d.ts.map +1 -0
- package/dist/social.js +88 -0
- package/dist/social.js.map +1 -0
- package/dist/stability.d.ts.map +1 -1
- package/dist/stability.js +84 -4
- package/dist/stability.js.map +1 -1
- package/dist/stream-parser.d.ts.map +1 -1
- package/dist/stream-parser.js +21 -1
- package/dist/stream-parser.js.map +1 -1
- package/dist/types.d.ts +92 -0
- package/dist/types.d.ts.map +1 -1
- package/examples/github-actions.yml +2 -2
- package/examples/ssrwire.config.yml +8 -2
- package/package.json +5 -2
- package/src/analyze.ts +208 -7
- package/src/audit-report.ts +269 -0
- package/src/audit.ts +2 -0
- package/src/cli.ts +106 -12
- package/src/compare.ts +949 -0
- package/src/comparison-reporters.ts +276 -0
- package/src/config.ts +19 -1
- package/src/http-probe.ts +4 -0
- package/src/index.ts +29 -0
- package/src/redact.ts +6 -0
- package/src/reporters.ts +46 -0
- package/src/social.ts +116 -0
- package/src/stability.ts +123 -4
- package/src/stream-parser.ts +31 -1
- package/src/types.ts +117 -0
package/dist/types.d.ts
CHANGED
|
@@ -12,6 +12,10 @@ export type RobotsAudience = "robots" | "googlebot" | "bingbot";
|
|
|
12
12
|
export interface RobotsSignal extends ElementSignal {
|
|
13
13
|
readonly audience: RobotsAudience;
|
|
14
14
|
}
|
|
15
|
+
export type SocialMetadataProperty = "og:title" | "og:type" | "og:url" | "og:image" | "og:description" | "twitter:card" | "twitter:title" | "twitter:description" | "twitter:image";
|
|
16
|
+
export interface SocialMetadataSignal extends ElementSignal {
|
|
17
|
+
readonly property: SocialMetadataProperty;
|
|
18
|
+
}
|
|
15
19
|
export interface JsonLdSignal extends TimingMark {
|
|
16
20
|
readonly location: ElementLocation;
|
|
17
21
|
readonly valid?: boolean;
|
|
@@ -26,6 +30,8 @@ export interface DocumentSignals {
|
|
|
26
30
|
readonly descriptions: readonly ElementSignal[];
|
|
27
31
|
readonly canonicals: readonly ElementSignal[];
|
|
28
32
|
readonly robots: readonly RobotsSignal[];
|
|
33
|
+
/** Present on current probes; optional for low-level callers and older in-memory results. */
|
|
34
|
+
readonly socialMetadata?: readonly SocialMetadataSignal[];
|
|
29
35
|
readonly h1s: readonly ElementSignal[];
|
|
30
36
|
readonly firstMainText?: ElementSignal;
|
|
31
37
|
readonly jsonLd: readonly JsonLdSignal[];
|
|
@@ -89,10 +95,16 @@ export interface TargetExpectations {
|
|
|
89
95
|
readonly requireCanonical: boolean;
|
|
90
96
|
readonly requireH1: boolean;
|
|
91
97
|
readonly requireMainText: boolean;
|
|
98
|
+
/** Require the four Open Graph protocol basic metadata properties. Defaults to false. */
|
|
99
|
+
readonly requireOpenGraph?: boolean;
|
|
100
|
+
/** Require SSRWire's Twitter Card readiness contract. Defaults to false. */
|
|
101
|
+
readonly requireTwitterCard?: boolean;
|
|
92
102
|
readonly maxFirstByteMs?: number;
|
|
93
103
|
readonly maxCriticalMs?: number;
|
|
94
104
|
}
|
|
95
105
|
export interface AuditTarget {
|
|
106
|
+
/** Stable identity used to match the same target across reports with different origins. */
|
|
107
|
+
readonly id?: string;
|
|
96
108
|
readonly url: string;
|
|
97
109
|
readonly expectations: TargetExpectations;
|
|
98
110
|
}
|
|
@@ -160,6 +172,8 @@ export interface AuditSummary {
|
|
|
160
172
|
readonly incomplete: number;
|
|
161
173
|
}
|
|
162
174
|
export interface AuditResult {
|
|
175
|
+
/** Version of the persisted audit-report contract, independent of the package version. */
|
|
176
|
+
readonly schemaVersion: 1;
|
|
163
177
|
readonly version: string;
|
|
164
178
|
readonly generatedAt: string;
|
|
165
179
|
readonly durationMs: number;
|
|
@@ -168,4 +182,82 @@ export interface AuditResult {
|
|
|
168
182
|
readonly summary: AuditSummary;
|
|
169
183
|
}
|
|
170
184
|
export type ReportFormat = "terminal" | "json" | "sarif";
|
|
185
|
+
export type ComparisonKind = "regression" | "fixed" | "changed";
|
|
186
|
+
export type ComparisonScope = "target" | "agent" | "finding" | "response" | "metadata" | "timing";
|
|
187
|
+
export interface ComparisonChange {
|
|
188
|
+
readonly kind: ComparisonKind;
|
|
189
|
+
readonly scope: ComparisonScope;
|
|
190
|
+
readonly code: string;
|
|
191
|
+
readonly message: string;
|
|
192
|
+
readonly agent?: string;
|
|
193
|
+
readonly field?: string;
|
|
194
|
+
readonly baseline?: string | number | boolean;
|
|
195
|
+
readonly candidate?: string | number | boolean;
|
|
196
|
+
}
|
|
197
|
+
export interface ComparisonTimelineEvent {
|
|
198
|
+
readonly key: string;
|
|
199
|
+
readonly label: string;
|
|
200
|
+
readonly medianMs: number;
|
|
201
|
+
readonly location?: ElementLocation | "mixed";
|
|
202
|
+
readonly observedByByte?: number;
|
|
203
|
+
}
|
|
204
|
+
export interface ComparisonTimelineSnapshot {
|
|
205
|
+
readonly samples: number;
|
|
206
|
+
readonly events: readonly ComparisonTimelineEvent[];
|
|
207
|
+
}
|
|
208
|
+
export interface ComparisonTimelineLane {
|
|
209
|
+
readonly agent: string;
|
|
210
|
+
readonly label: string;
|
|
211
|
+
readonly baseline?: ComparisonTimelineSnapshot;
|
|
212
|
+
readonly candidate?: ComparisonTimelineSnapshot;
|
|
213
|
+
}
|
|
214
|
+
export type TargetComparisonStatus = "matched" | "added" | "removed";
|
|
215
|
+
export interface TargetComparison {
|
|
216
|
+
readonly key: string;
|
|
217
|
+
readonly id?: string;
|
|
218
|
+
readonly status: TargetComparisonStatus;
|
|
219
|
+
readonly baselineUrl?: string;
|
|
220
|
+
readonly candidateUrl?: string;
|
|
221
|
+
readonly changes: readonly ComparisonChange[];
|
|
222
|
+
readonly timelines: readonly ComparisonTimelineLane[];
|
|
223
|
+
}
|
|
224
|
+
export interface AuditReportDescriptor {
|
|
225
|
+
readonly label: string;
|
|
226
|
+
readonly version: string;
|
|
227
|
+
readonly schemaVersion: 1;
|
|
228
|
+
readonly generatedAt: string;
|
|
229
|
+
readonly repeat: number;
|
|
230
|
+
}
|
|
231
|
+
export interface ComparisonThresholds {
|
|
232
|
+
readonly timingRegressionMs: number;
|
|
233
|
+
readonly timingRegressionPercent: number;
|
|
234
|
+
}
|
|
235
|
+
export interface ComparisonSummary {
|
|
236
|
+
readonly targets: number;
|
|
237
|
+
readonly matchedTargets: number;
|
|
238
|
+
readonly addedTargets: number;
|
|
239
|
+
readonly removedTargets: number;
|
|
240
|
+
readonly unchangedTargets: number;
|
|
241
|
+
readonly regressions: number;
|
|
242
|
+
readonly fixed: number;
|
|
243
|
+
readonly changed: number;
|
|
244
|
+
}
|
|
245
|
+
export interface AuditComparison {
|
|
246
|
+
readonly schemaVersion: 1;
|
|
247
|
+
readonly kind: "comparison";
|
|
248
|
+
readonly version: string;
|
|
249
|
+
readonly generatedAt: string;
|
|
250
|
+
readonly baseline: AuditReportDescriptor;
|
|
251
|
+
readonly candidate: AuditReportDescriptor;
|
|
252
|
+
readonly thresholds: ComparisonThresholds;
|
|
253
|
+
readonly results: readonly TargetComparison[];
|
|
254
|
+
readonly summary: ComparisonSummary;
|
|
255
|
+
}
|
|
256
|
+
export interface CompareAuditOptions {
|
|
257
|
+
readonly baselineLabel?: string;
|
|
258
|
+
readonly candidateLabel?: string;
|
|
259
|
+
readonly timingRegressionMs?: number;
|
|
260
|
+
readonly timingRegressionPercent?: number;
|
|
261
|
+
}
|
|
262
|
+
export type ComparisonReportFormat = "terminal" | "json" | "html";
|
|
171
263
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -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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"}
|
|
@@ -27,7 +27,7 @@ jobs:
|
|
|
27
27
|
if: github.event_name == 'pull_request'
|
|
28
28
|
continue-on-error: true
|
|
29
29
|
run: >-
|
|
30
|
-
npx --yes ssrwire@0.
|
|
30
|
+
npx --yes ssrwire@0.4.0 check
|
|
31
31
|
--config ssrwire.config.yml
|
|
32
32
|
--format sarif
|
|
33
33
|
--output reports/ssrwire.sarif
|
|
@@ -38,7 +38,7 @@ jobs:
|
|
|
38
38
|
if: github.event_name != 'pull_request'
|
|
39
39
|
continue-on-error: true
|
|
40
40
|
run: >-
|
|
41
|
-
npx --yes ssrwire@0.
|
|
41
|
+
npx --yes ssrwire@0.4.0 check
|
|
42
42
|
--config ssrwire.config.yml
|
|
43
43
|
--format sarif
|
|
44
44
|
--output reports/ssrwire.sarif
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Replace these URLs with a small set of high-value SSR routes.
|
|
2
2
|
targets:
|
|
3
|
-
-
|
|
3
|
+
- id: home
|
|
4
|
+
url: https://example.com/
|
|
4
5
|
expectedStatus: 200
|
|
5
6
|
expectedFinalUrl: https://example.com/
|
|
6
7
|
require:
|
|
@@ -9,8 +10,11 @@ targets:
|
|
|
9
10
|
canonical: true
|
|
10
11
|
h1: true
|
|
11
12
|
mainText: true
|
|
13
|
+
openGraph: true
|
|
14
|
+
twitterCard: true
|
|
12
15
|
|
|
13
|
-
-
|
|
16
|
+
- id: pricing
|
|
17
|
+
url: https://example.com/pricing/
|
|
14
18
|
expectedStatus: 200
|
|
15
19
|
require:
|
|
16
20
|
title: true
|
|
@@ -18,6 +22,8 @@ targets:
|
|
|
18
22
|
canonical: true
|
|
19
23
|
h1: true
|
|
20
24
|
mainText: true
|
|
25
|
+
openGraph: false
|
|
26
|
+
twitterCard: false
|
|
21
27
|
|
|
22
28
|
# Add maxFirstByteMs or maxCriticalMs per target only when the runner location
|
|
23
29
|
# and cache state are stable enough for a meaningful threshold.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ssrwire",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Inspect streamed SSR HTML, metadata timing, and crawler-specific delivery from the command line.",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Inspect streamed SSR HTML, SEO and social metadata timing, and crawler-specific delivery from the command line.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"ssrwire": "./dist/bin.js"
|
|
@@ -52,6 +52,9 @@
|
|
|
52
52
|
"cli",
|
|
53
53
|
"typescript",
|
|
54
54
|
"seo-tools",
|
|
55
|
+
"open-graph",
|
|
56
|
+
"social-preview",
|
|
57
|
+
"twitter-cards",
|
|
55
58
|
"github-actions",
|
|
56
59
|
"sarif"
|
|
57
60
|
],
|
package/src/analyze.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
effectiveTwitterCardSignal,
|
|
3
|
+
firstSocialSignal,
|
|
4
|
+
isAbsoluteHttpSocialUrl,
|
|
5
|
+
normalizeSocialValue,
|
|
6
|
+
OPEN_GRAPH_PROPERTIES,
|
|
7
|
+
OPEN_GRAPH_REQUIRED_PROPERTIES,
|
|
8
|
+
socialSignals,
|
|
9
|
+
TWITTER_CARD_REQUIRED_FIELDS,
|
|
10
|
+
TWITTER_PROPERTIES,
|
|
11
|
+
} from "./social.js";
|
|
1
12
|
import type {
|
|
2
13
|
AuditSummary,
|
|
3
14
|
AuditTarget,
|
|
@@ -7,6 +18,8 @@ import type {
|
|
|
7
18
|
RobotsAudience,
|
|
8
19
|
RobotsSignal,
|
|
9
20
|
Severity,
|
|
21
|
+
SocialMetadataProperty,
|
|
22
|
+
SocialMetadataSignal,
|
|
10
23
|
TargetAuditResult,
|
|
11
24
|
} from "./types.js";
|
|
12
25
|
|
|
@@ -264,6 +277,146 @@ function checkRepeatedRobots(findings: Finding[], targetUrl: string, probe: Prob
|
|
|
264
277
|
}
|
|
265
278
|
}
|
|
266
279
|
|
|
280
|
+
function auditedSocialProperties(
|
|
281
|
+
target: AuditTarget,
|
|
282
|
+
probe: ProbeResult,
|
|
283
|
+
): readonly SocialMetadataProperty[] {
|
|
284
|
+
const properties = new Set<SocialMetadataProperty>();
|
|
285
|
+
if (target.expectations.requireOpenGraph === true) {
|
|
286
|
+
for (const property of OPEN_GRAPH_PROPERTIES) properties.add(property);
|
|
287
|
+
}
|
|
288
|
+
if (target.expectations.requireTwitterCard === true) {
|
|
289
|
+
for (const property of TWITTER_PROPERTIES) properties.add(property);
|
|
290
|
+
if (firstSocialSignal(probe.signals, "twitter:title") === undefined) {
|
|
291
|
+
properties.add("og:title");
|
|
292
|
+
}
|
|
293
|
+
if (firstSocialSignal(probe.signals, "twitter:description") === undefined) {
|
|
294
|
+
properties.add("og:description");
|
|
295
|
+
}
|
|
296
|
+
if (firstSocialSignal(probe.signals, "twitter:image") === undefined) {
|
|
297
|
+
properties.add("og:image");
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return [...properties];
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function normalizedSocialValues(
|
|
304
|
+
property: SocialMetadataProperty,
|
|
305
|
+
signals: readonly SocialMetadataSignal[],
|
|
306
|
+
baseUrl: string,
|
|
307
|
+
): readonly string[] {
|
|
308
|
+
return signals
|
|
309
|
+
.map((signal) => normalizeSocialValue(property, signal.value, baseUrl))
|
|
310
|
+
.filter((value) => value.length > 0);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function checkRepeatedSocialMetadata(
|
|
314
|
+
findings: Finding[],
|
|
315
|
+
target: AuditTarget,
|
|
316
|
+
probe: ProbeResult,
|
|
317
|
+
): void {
|
|
318
|
+
for (const property of auditedSocialProperties(target, probe)) {
|
|
319
|
+
// Open Graph explicitly permits multiple images and gives the first one precedence.
|
|
320
|
+
if (property === "og:image") continue;
|
|
321
|
+
const values = normalizedSocialValues(
|
|
322
|
+
property,
|
|
323
|
+
socialSignals(probe.signals, property),
|
|
324
|
+
probe.finalUrl,
|
|
325
|
+
);
|
|
326
|
+
if (values.length < 2) continue;
|
|
327
|
+
|
|
328
|
+
const distinct = new Set(values);
|
|
329
|
+
const conflicting = distinct.size > 1;
|
|
330
|
+
addFinding(findings, target.url, {
|
|
331
|
+
code: conflicting ? "conflicting-social-metadata" : "duplicate-social-metadata",
|
|
332
|
+
severity: "warning",
|
|
333
|
+
message: conflicting
|
|
334
|
+
? `${probe.agent.label} received conflicting ${property} values.`
|
|
335
|
+
: `${probe.agent.label} received duplicate ${property} values.`,
|
|
336
|
+
agent: probe.agent.key,
|
|
337
|
+
evidence: {
|
|
338
|
+
property,
|
|
339
|
+
count: values.length,
|
|
340
|
+
distinctValues: distinct.size,
|
|
341
|
+
values: [...distinct].join(" | "),
|
|
342
|
+
},
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function checkSocialUrls(findings: Finding[], target: AuditTarget, probe: ProbeResult): void {
|
|
348
|
+
const candidates = new Set<SocialMetadataSignal>();
|
|
349
|
+
if (target.expectations.requireOpenGraph === true) {
|
|
350
|
+
for (const signal of socialSignals(probe.signals, "og:url")) candidates.add(signal);
|
|
351
|
+
for (const signal of socialSignals(probe.signals, "og:image")) candidates.add(signal);
|
|
352
|
+
}
|
|
353
|
+
if (target.expectations.requireTwitterCard === true) {
|
|
354
|
+
const image = effectiveTwitterCardSignal(probe.signals, "image");
|
|
355
|
+
if (image !== undefined) candidates.add(image);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
for (const signal of candidates) {
|
|
359
|
+
if (signal.value.trim().length === 0 || isAbsoluteHttpSocialUrl(signal.value)) continue;
|
|
360
|
+
addFinding(findings, target.url, {
|
|
361
|
+
code: "invalid-social-metadata-url",
|
|
362
|
+
severity: "warning",
|
|
363
|
+
message: `${probe.agent.label} received a non-absolute HTTP(S) ${signal.property} URL.`,
|
|
364
|
+
agent: probe.agent.key,
|
|
365
|
+
evidence: { property: signal.property, value: signal.value },
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function checkRequiredSocialMetadata(
|
|
371
|
+
findings: Finding[],
|
|
372
|
+
target: AuditTarget,
|
|
373
|
+
probe: ProbeResult,
|
|
374
|
+
): void {
|
|
375
|
+
if (probe.completion !== "complete") return;
|
|
376
|
+
|
|
377
|
+
if (target.expectations.requireOpenGraph === true) {
|
|
378
|
+
const missing = OPEN_GRAPH_REQUIRED_PROPERTIES.filter(
|
|
379
|
+
(property) => firstSocialSignal(probe.signals, property) === undefined,
|
|
380
|
+
);
|
|
381
|
+
if (missing.length > 0) {
|
|
382
|
+
addFinding(findings, target.url, {
|
|
383
|
+
code: "missing-open-graph-metadata",
|
|
384
|
+
severity: "warning",
|
|
385
|
+
message: `${probe.agent.label} received an incomplete Open Graph metadata set.`,
|
|
386
|
+
agent: probe.agent.key,
|
|
387
|
+
evidence: { fields: missing.join(", ") },
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
if (target.expectations.requireTwitterCard === true) {
|
|
393
|
+
const missing = TWITTER_CARD_REQUIRED_FIELDS.filter(
|
|
394
|
+
(field) => effectiveTwitterCardSignal(probe.signals, field) === undefined,
|
|
395
|
+
);
|
|
396
|
+
if (missing.length > 0) {
|
|
397
|
+
addFinding(findings, target.url, {
|
|
398
|
+
code: "missing-twitter-card-metadata",
|
|
399
|
+
severity: "warning",
|
|
400
|
+
message: `${probe.agent.label} received an incomplete Twitter Card metadata set.`,
|
|
401
|
+
agent: probe.agent.key,
|
|
402
|
+
evidence: { fields: missing.join(", ") },
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function checkSocialMetadata(findings: Finding[], target: AuditTarget, probe: ProbeResult): void {
|
|
409
|
+
if (
|
|
410
|
+
target.expectations.requireOpenGraph !== true &&
|
|
411
|
+
target.expectations.requireTwitterCard !== true
|
|
412
|
+
) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
checkRequiredSocialMetadata(findings, target, probe);
|
|
416
|
+
checkRepeatedSocialMetadata(findings, target, probe);
|
|
417
|
+
checkSocialUrls(findings, target, probe);
|
|
418
|
+
}
|
|
419
|
+
|
|
267
420
|
function criticalArrivalMs(target: AuditTarget, probe: ProbeResult): number | undefined {
|
|
268
421
|
const marks: number[] = [];
|
|
269
422
|
const { expectations } = target;
|
|
@@ -299,6 +452,20 @@ function criticalArrivalMs(target: AuditTarget, probe: ProbeResult): number | un
|
|
|
299
452
|
) {
|
|
300
453
|
marks.push(probe.signals.firstMainText?.atMs ?? 0);
|
|
301
454
|
}
|
|
455
|
+
if (expectations.requireOpenGraph === true) {
|
|
456
|
+
const signals = OPEN_GRAPH_REQUIRED_PROPERTIES.map((property) =>
|
|
457
|
+
firstSocialSignal(probe.signals, property),
|
|
458
|
+
);
|
|
459
|
+
if (!signals.every((signal) => signal !== undefined)) return undefined;
|
|
460
|
+
marks.push(...signals.map((signal) => signal.atMs));
|
|
461
|
+
}
|
|
462
|
+
if (expectations.requireTwitterCard === true) {
|
|
463
|
+
const signals = TWITTER_CARD_REQUIRED_FIELDS.map((field) =>
|
|
464
|
+
effectiveTwitterCardSignal(probe.signals, field),
|
|
465
|
+
);
|
|
466
|
+
if (!signals.every((signal) => signal !== undefined)) return undefined;
|
|
467
|
+
marks.push(...signals.map((signal) => signal.atMs));
|
|
468
|
+
}
|
|
302
469
|
|
|
303
470
|
return marks.length === 0 ? undefined : Math.max(...marks);
|
|
304
471
|
}
|
|
@@ -365,7 +532,7 @@ function checkRequiredSignals(findings: Finding[], target: AuditTarget, probe: P
|
|
|
365
532
|
}
|
|
366
533
|
}
|
|
367
534
|
|
|
368
|
-
function checkHeadRequirements(findings: Finding[],
|
|
535
|
+
function checkHeadRequirements(findings: Finding[], target: AuditTarget, probe: ProbeResult): void {
|
|
369
536
|
if (!probe.agent.requiresHeadMetadata) {
|
|
370
537
|
return;
|
|
371
538
|
}
|
|
@@ -384,12 +551,17 @@ function checkHeadRequirements(findings: Finding[], targetUrl: string, probe: Pr
|
|
|
384
551
|
if (effectiveRobotsSignals(probe).some((signal) => signal.location === "body")) {
|
|
385
552
|
bodyFields.add("robots");
|
|
386
553
|
}
|
|
554
|
+
for (const property of auditedSocialProperties(target, probe)) {
|
|
555
|
+
if (socialSignals(probe.signals, property).some((signal) => signal.location === "body")) {
|
|
556
|
+
bodyFields.add(property);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
387
559
|
|
|
388
560
|
if (bodyFields.size === 0) {
|
|
389
561
|
return;
|
|
390
562
|
}
|
|
391
563
|
|
|
392
|
-
addFinding(findings,
|
|
564
|
+
addFinding(findings, target.url, {
|
|
393
565
|
code: "head-metadata-in-body",
|
|
394
566
|
severity: "error",
|
|
395
567
|
message: `${probe.agent.label} requires head metadata but received ${[...bodyFields].join(
|
|
@@ -440,9 +612,31 @@ function agentValueSummary(
|
|
|
440
612
|
return probes.map((probe) => `${probe.agent.key}=${valueFor(probe)}`).join("; ");
|
|
441
613
|
}
|
|
442
614
|
|
|
615
|
+
function openGraphValue(probe: ProbeResult): string {
|
|
616
|
+
return OPEN_GRAPH_PROPERTIES.map((property) => {
|
|
617
|
+
const values = [
|
|
618
|
+
...new Set(
|
|
619
|
+
normalizedSocialValues(property, socialSignals(probe.signals, property), probe.finalUrl),
|
|
620
|
+
),
|
|
621
|
+
];
|
|
622
|
+
return `${property}=${values.join(" | ") || "<missing>"}`;
|
|
623
|
+
}).join(", ");
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
function twitterCardValue(probe: ProbeResult): string {
|
|
627
|
+
return TWITTER_CARD_REQUIRED_FIELDS.map((field) => {
|
|
628
|
+
const signal = effectiveTwitterCardSignal(probe.signals, field);
|
|
629
|
+
const value =
|
|
630
|
+
signal === undefined
|
|
631
|
+
? "<missing>"
|
|
632
|
+
: normalizeSocialValue(signal.property, signal.value, probe.finalUrl);
|
|
633
|
+
return `${field}=${value || "<missing>"}`;
|
|
634
|
+
}).join(", ");
|
|
635
|
+
}
|
|
636
|
+
|
|
443
637
|
function checkAgentDrift(
|
|
444
638
|
findings: Finding[],
|
|
445
|
-
|
|
639
|
+
target: AuditTarget,
|
|
446
640
|
probes: readonly ProbeResult[],
|
|
447
641
|
): void {
|
|
448
642
|
const complete = probes.filter((probe) => probe.completion === "complete");
|
|
@@ -450,7 +644,7 @@ function checkAgentDrift(
|
|
|
450
644
|
return;
|
|
451
645
|
}
|
|
452
646
|
|
|
453
|
-
const comparisons:
|
|
647
|
+
const comparisons: {
|
|
454
648
|
readonly field: string;
|
|
455
649
|
readonly valueFor: (probe: ProbeResult) => string;
|
|
456
650
|
}[] = [
|
|
@@ -472,6 +666,12 @@ function checkAgentDrift(
|
|
|
472
666
|
valueFor: effectiveRobotsValue,
|
|
473
667
|
},
|
|
474
668
|
];
|
|
669
|
+
if (target.expectations.requireOpenGraph === true) {
|
|
670
|
+
comparisons.push({ field: "open-graph", valueFor: openGraphValue });
|
|
671
|
+
}
|
|
672
|
+
if (target.expectations.requireTwitterCard === true) {
|
|
673
|
+
comparisons.push({ field: "twitter-card", valueFor: twitterCardValue });
|
|
674
|
+
}
|
|
475
675
|
|
|
476
676
|
for (const comparison of comparisons) {
|
|
477
677
|
const values = complete.map(comparison.valueFor);
|
|
@@ -479,7 +679,7 @@ function checkAgentDrift(
|
|
|
479
679
|
continue;
|
|
480
680
|
}
|
|
481
681
|
|
|
482
|
-
addFinding(findings,
|
|
682
|
+
addFinding(findings, target.url, {
|
|
483
683
|
code: `agent-${comparison.field}-drift`,
|
|
484
684
|
severity: "warning",
|
|
485
685
|
message: `Crawler profiles received different ${comparison.field.replace("-", " ")} values.`,
|
|
@@ -556,6 +756,7 @@ export function analyzeTarget(
|
|
|
556
756
|
checkRepeatedMetadata(findings, target.url, probe, "description", probe.signals.descriptions);
|
|
557
757
|
checkRepeatedMetadata(findings, target.url, probe, "canonical", probe.signals.canonicals);
|
|
558
758
|
checkRepeatedRobots(findings, target.url, probe);
|
|
759
|
+
checkSocialMetadata(findings, target, probe);
|
|
559
760
|
|
|
560
761
|
const invalidJsonLd = probe.signals.jsonLd.filter((signal) => signal.valid === false);
|
|
561
762
|
if (probe.completion === "complete" && invalidJsonLd.length > 0) {
|
|
@@ -587,11 +788,11 @@ export function analyzeTarget(
|
|
|
587
788
|
});
|
|
588
789
|
}
|
|
589
790
|
|
|
590
|
-
checkHeadRequirements(findings, target
|
|
791
|
+
checkHeadRequirements(findings, target, probe);
|
|
591
792
|
checkTimings(findings, target, probe);
|
|
592
793
|
}
|
|
593
794
|
|
|
594
|
-
checkAgentDrift(findings, target
|
|
795
|
+
checkAgentDrift(findings, target, probes);
|
|
595
796
|
|
|
596
797
|
return findings;
|
|
597
798
|
}
|