@eightmedia/flightcheck 0.0.0-stage → 0.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 (127) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +691 -0
  3. package/README.md +106 -2
  4. package/dist/analyze/fixManifest.d.ts +65 -0
  5. package/dist/analyze/fixManifest.d.ts.map +1 -0
  6. package/dist/analyze/fixManifest.js +588 -0
  7. package/dist/analyze/report.d.ts +283 -0
  8. package/dist/analyze/report.d.ts.map +1 -0
  9. package/dist/analyze/report.js +726 -0
  10. package/dist/analyze/reportTier1.d.ts +46 -0
  11. package/dist/analyze/reportTier1.d.ts.map +1 -0
  12. package/dist/analyze/reportTier1.js +251 -0
  13. package/dist/analyze/stack.d.ts +33 -0
  14. package/dist/analyze/stack.d.ts.map +1 -0
  15. package/dist/analyze/stack.js +188 -0
  16. package/dist/analyze/structuredReport.d.ts +62 -0
  17. package/dist/analyze/structuredReport.d.ts.map +1 -0
  18. package/dist/analyze/structuredReport.js +524 -0
  19. package/dist/analyze.d.ts +3 -0
  20. package/dist/analyze.d.ts.map +1 -0
  21. package/dist/analyze.js +40 -0
  22. package/dist/checks/agent-ready.d.ts +63 -0
  23. package/dist/checks/agent-ready.d.ts.map +1 -0
  24. package/dist/checks/agent-ready.js +219 -0
  25. package/dist/checks/analyze.d.ts +15 -0
  26. package/dist/checks/analyze.d.ts.map +1 -0
  27. package/dist/checks/analyze.js +63 -0
  28. package/dist/checks/crawl.d.ts +28 -0
  29. package/dist/checks/crawl.d.ts.map +1 -0
  30. package/dist/checks/crawl.js +86 -0
  31. package/dist/checks/dns.d.ts +25 -0
  32. package/dist/checks/dns.d.ts.map +1 -0
  33. package/dist/checks/dns.js +80 -0
  34. package/dist/checks/index.d.ts +24 -0
  35. package/dist/checks/index.d.ts.map +1 -0
  36. package/dist/checks/index.js +12 -0
  37. package/dist/checks/issues.d.ts +8 -0
  38. package/dist/checks/issues.d.ts.map +1 -0
  39. package/dist/checks/issues.js +3 -0
  40. package/dist/checks/redirect.d.ts +38 -0
  41. package/dist/checks/redirect.d.ts.map +1 -0
  42. package/dist/checks/redirect.js +209 -0
  43. package/dist/checks/registry.d.ts +8 -0
  44. package/dist/checks/registry.d.ts.map +1 -0
  45. package/dist/checks/registry.js +275 -0
  46. package/dist/checks/robots-txt.d.ts +16 -0
  47. package/dist/checks/robots-txt.d.ts.map +1 -0
  48. package/dist/checks/robots-txt.js +99 -0
  49. package/dist/checks/runner.d.ts +9 -0
  50. package/dist/checks/runner.d.ts.map +1 -0
  51. package/dist/checks/runner.js +110 -0
  52. package/dist/checks/security-headers.d.ts +12 -0
  53. package/dist/checks/security-headers.d.ts.map +1 -0
  54. package/dist/checks/security-headers.js +53 -0
  55. package/dist/checks/sitemap.d.ts +36 -0
  56. package/dist/checks/sitemap.d.ts.map +1 -0
  57. package/dist/checks/sitemap.js +140 -0
  58. package/dist/checks/types.d.ts +72 -0
  59. package/dist/checks/types.d.ts.map +1 -0
  60. package/dist/checks/types.js +20 -0
  61. package/dist/cli.d.ts +3 -0
  62. package/dist/cli.d.ts.map +1 -0
  63. package/dist/cli.js +125 -0
  64. package/dist/crawler/checkGroups.d.ts +7 -0
  65. package/dist/crawler/checkGroups.d.ts.map +1 -0
  66. package/dist/crawler/checkGroups.js +29 -0
  67. package/dist/crawler/crawlState.d.ts +7 -0
  68. package/dist/crawler/crawlState.d.ts.map +1 -0
  69. package/dist/crawler/crawlState.js +6 -0
  70. package/dist/crawler/defaults.d.ts +11 -0
  71. package/dist/crawler/defaults.d.ts.map +1 -0
  72. package/dist/crawler/defaults.js +10 -0
  73. package/dist/crawler/extractors.d.ts +5 -0
  74. package/dist/crawler/extractors.d.ts.map +1 -0
  75. package/dist/crawler/extractors.js +169 -0
  76. package/dist/crawler/jsAssets.d.ts +2 -0
  77. package/dist/crawler/jsAssets.d.ts.map +1 -0
  78. package/dist/crawler/jsAssets.js +22 -0
  79. package/dist/crawler/outputPaths.d.ts +14 -0
  80. package/dist/crawler/outputPaths.d.ts.map +1 -0
  81. package/dist/crawler/outputPaths.js +51 -0
  82. package/dist/crawler/reporter.d.ts +3 -0
  83. package/dist/crawler/reporter.d.ts.map +1 -0
  84. package/dist/crawler/reporter.js +12 -0
  85. package/dist/crawler/robots.d.ts +5 -0
  86. package/dist/crawler/robots.d.ts.map +1 -0
  87. package/dist/crawler/robots.js +29 -0
  88. package/dist/crawler/runCrawler.d.ts +22 -0
  89. package/dist/crawler/runCrawler.d.ts.map +1 -0
  90. package/dist/crawler/runCrawler.js +172 -0
  91. package/dist/crawler/schema.d.ts +87 -0
  92. package/dist/crawler/schema.d.ts.map +1 -0
  93. package/dist/crawler/schema.js +44 -0
  94. package/dist/crawler/secrets.d.ts +4 -0
  95. package/dist/crawler/secrets.d.ts.map +1 -0
  96. package/dist/crawler/secrets.js +70 -0
  97. package/dist/crawler/sitemap.d.ts +8 -0
  98. package/dist/crawler/sitemap.d.ts.map +1 -0
  99. package/dist/crawler/sitemap.js +105 -0
  100. package/dist/crawler/stack.d.ts +3 -0
  101. package/dist/crawler/stack.d.ts.map +1 -0
  102. package/dist/crawler/stack.js +1 -0
  103. package/dist/crawler/stackDetect.d.ts +24 -0
  104. package/dist/crawler/stackDetect.d.ts.map +1 -0
  105. package/dist/crawler/stackDetect.js +604 -0
  106. package/dist/crawler/tier1Extractors.d.ts +5 -0
  107. package/dist/crawler/tier1Extractors.d.ts.map +1 -0
  108. package/dist/crawler/tier1Extractors.js +255 -0
  109. package/dist/crawler/tracking.d.ts +8 -0
  110. package/dist/crawler/tracking.d.ts.map +1 -0
  111. package/dist/crawler/tracking.js +50 -0
  112. package/dist/crawler/urlUtils.d.ts +12 -0
  113. package/dist/crawler/urlUtils.d.ts.map +1 -0
  114. package/dist/crawler/urlUtils.js +53 -0
  115. package/dist/index.d.ts +14 -0
  116. package/dist/index.d.ts.map +1 -0
  117. package/dist/index.js +7 -0
  118. package/docs/agent-fixes.md +17 -0
  119. package/docs/agent-ready.md +44 -0
  120. package/docs/analyze.md +103 -0
  121. package/docs/check-api.md +142 -0
  122. package/docs/checks.md +116 -0
  123. package/docs/crawler.md +158 -0
  124. package/docs/index.md +24 -0
  125. package/docs/qc-checks-plan.md +796 -0
  126. package/docs/stack.md +99 -0
  127. package/package.json +86 -4
@@ -0,0 +1,142 @@
1
+ # Flightcheck check API
2
+
3
+ Flightcheck is built as a modular check system. Each check is a standalone exported
4
+ function that can run on its own, be exposed as an API endpoint, or be orchestrated
5
+ together by the CLI.
6
+
7
+ For a plain-language list of what is audited, see [checks.md](./checks.md).
8
+
9
+ ## Available checks
10
+
11
+ | ID | Status | Description |
12
+ | --- | --- | --- |
13
+ | `crawl` | implemented | Crawl pages and collect SEO, metadata, tracking, and security data |
14
+ | `analyze` | implemented | Turn crawl JSON into `*-report.json` + human-readable `*-report.md` |
15
+ | `security-headers` | implemented | Verify HTTP security headers (CSP, HSTS, etc.) |
16
+ | `dns` | implemented | Verify DNS records, SPF/DMARC, and domain ownership signals. SPF/DMARC missing-record warnings are skipped on Vercel/Netlify platform preview hostnames (`*.vercel.app`, `*.netlify.app`) |
17
+ | `robots-txt` | implemented | Report robots.txt presence, sitemap directives, and crawl blocks |
18
+ | `sitemap` | implemented | Verify sitemap exists and exactly matches crawled URLs (same hostname and path; follows sitemap index files; runs after crawl; seeds crawl with sitemap URLs) |
19
+ | `agent-ready` | implemented | AI agent discoverability: Content Signals, AI bot rules, llms.txt, Markdown negotiation, Link headers, well-known protocol cards |
20
+ | `lighthouse` | planned | Lighthouse performance, accessibility, and best-practices audits |
21
+ | `redirect` | implemented | Always-on pipeline check (not a `--checks` registry id): probes the start URL for HTTP redirects, validates the apex ↔ www alias (skipped on Vercel/Netlify platform preview hostnames), and drives redirect-only mode (`dns`, `analyze`) |
22
+
23
+ ### Crawl check groups (Tier 1)
24
+
25
+ When crawling, these optional groups extend per-page extraction:
26
+
27
+ | Group | Status | Description |
28
+ | --- | --- | --- |
29
+ | `images` | implemented | Image alt text issues (missing, empty, generic); decoded filenames from `src`/`srcset`/`<picture>` and `/_next/image` |
30
+ | `a11y-static` | implemented | Static accessibility hints (headings, labels, lang, tabindex) |
31
+
32
+ Use `--only images,a11y-static` or include them in the default crawl groups.
33
+
34
+ See `docs/qc-checks-plan.md` for the full tiered roadmap:
35
+
36
+ - **Tier 0/1** — crawl + fetch (SEO, headers, DNS, links, robots, sitemap — no browser)
37
+ - **Tier 2** — `a11y-axe` on 3–5 sampled URLs
38
+ - **Tier 3** — optional `performance` (Lighthouse or PageSpeed API)
39
+
40
+ ## Programmatic usage
41
+
42
+ Import from the package root or the checks subpath:
43
+
44
+ ```typescript
45
+ import { runChecks, runCrawlCheck, runAnalyzeCheck, listChecks } from "@eightmedia/flightcheck";
46
+ // or
47
+ import { runCheck, planCheckWaves } from "@eightmedia/flightcheck/checks";
48
+ ```
49
+
50
+ Run the default pipeline (all implemented checks):
51
+
52
+ ```typescript
53
+ const { outputs, results } = await runChecks({
54
+ startUrl: "https://example.com",
55
+ crawl: { maxPages: 100 },
56
+ analyze: { errorsOnly: false },
57
+ });
58
+ ```
59
+
60
+ Default checks: `crawl`, `security-headers`, `dns`, `robots-txt`, `sitemap`, `agent-ready`, `analyze`.
61
+
62
+ Run a single check:
63
+
64
+ ```typescript
65
+ const crawl = await runCrawlCheck({ startUrl: "https://example.com" });
66
+ const report = await runAnalyzeCheck({ records: crawl.records });
67
+ ```
68
+
69
+ Run independent Tier 1 checks in parallel:
70
+
71
+ ```typescript
72
+ await runChecks({
73
+ startUrl: "https://example.com",
74
+ checks: ["crawl", "security-headers", "dns", "robots-txt", "sitemap", "agent-ready", "analyze"],
75
+ parallel: true,
76
+ });
77
+ ```
78
+
79
+ Pure analysis helpers (no network) are also exported for tests and API use:
80
+
81
+ ```typescript
82
+ import {
83
+ analyzeSecurityHeaders,
84
+ analyzeRobotsTxt,
85
+ analyzeDnsRecords,
86
+ analyzeSitemapCompare,
87
+ analyzeAgentReady,
88
+ } from "@eightmedia/flightcheck/checks";
89
+ ```
90
+
91
+ Wave planning:
92
+
93
+ - Wave 1 (parallel-capable): `crawl`, `lighthouse`, `security-headers`, `dns`, `robots-txt`, `agent-ready`
94
+ - Wave 2 (after crawl): `sitemap`
95
+ - Wave 3: `analyze` (uses crawl output when available)
96
+
97
+ ## CLI
98
+
99
+ ```bash
100
+ pnpm run flightcheck -- https://example.com
101
+ pnpm run flightcheck -- https://example.com --parallel
102
+ pnpm run flightcheck -- https://example.com --checks crawl,analyze --parallel
103
+ pnpm run flightcheck -- https://example.com --checks crawl --json-only
104
+ ```
105
+
106
+ By default, `flightcheck` runs all implemented checks including sitemap validation. When the
107
+ start URL returns an HTTP redirect (for example apex → www), flightcheck automatically
108
+ switches to **redirect-only mode**: it validates the redirect and skips crawl, sitemap,
109
+ robots.txt, and security-headers checks. The redirect check also probes the alternate host
110
+ (apex ↔ www): the non-canonical host must permanently redirect to the canonical host implied
111
+ by the start URL (or its redirect target). That www-alias probe is skipped for Vercel and
112
+ Netlify platform preview hostnames (`*.vercel.app`, `*.netlify.app`), and the DNS check
113
+ likewise skips SPF/DMARC missing-record warnings on those hostnames. Use `--checks crawl`
114
+ to force a full crawl anyway.
115
+
116
+ Use `--checks` to run a subset. Add `--parallel` to run wave 1 checks concurrently.
117
+
118
+ ## Adding a new check
119
+
120
+ 1. Add the check ID to `CHECK_IDS` in `src/checks/types.ts`.
121
+ 2. Implement `runYourCheck()` in `src/checks/your-check.ts`.
122
+ 3. Register it in `src/checks/registry.ts` with `implemented: true`.
123
+ 4. Export it from `src/checks/index.ts`.
124
+ 5. Update `planCheckWaves()` if the check has special ordering rules.
125
+
126
+ Each check should:
127
+
128
+ - Accept typed input options
129
+ - Return typed result data
130
+ - Avoid coupling to CLI or filesystem when possible (allow in-memory results for API use)
131
+
132
+ ## API endpoint mapping
133
+
134
+ In a consuming project, map checks to endpoints:
135
+
136
+ - `POST /checks/crawl` → `runCrawlCheck`
137
+ - `POST /checks/analyze` → `runAnalyzeCheck`
138
+ - `POST /checks/run` → `runChecks`
139
+ - `GET /checks` → `listChecks`
140
+
141
+ This keeps one check per route and makes it straightforward to run checks in separate
142
+ workers or threads.
package/docs/checks.md ADDED
@@ -0,0 +1,116 @@
1
+ # What Flightcheck checks
2
+
3
+ Simple overview of everything Flightcheck looks at when it audits a site.
4
+ Written for anyone who wants to know what is covered — no technical setup required.
5
+
6
+ For developers implementing or extending checks, see [check-api.md](./check-api.md).
7
+
8
+ ## On every page (SEO & basics)
9
+
10
+ - Page title
11
+ - Heading (h1)
12
+ - Meta description
13
+ - Robots meta (e.g. noindex / nofollow)
14
+ - Template marker
15
+ - Meta title
16
+ - Character encoding (charset)
17
+ - Language
18
+ - Viewport (mobile-friendly)
19
+ - Doctype
20
+ - Canonical URL
21
+ - Color scheme
22
+ - Theme color
23
+ - Main content landmark (`<main>` — exactly one)
24
+
25
+ ## Sharing & social previews
26
+
27
+ - Open Graph title
28
+ - Open Graph description
29
+ - Open Graph image
30
+ - Open Graph URL
31
+ - Open Graph type
32
+ - Open Graph site name
33
+ - Twitter card type
34
+ - Twitter title
35
+ - Twitter description
36
+ - Twitter image
37
+
38
+ ## Icons
39
+
40
+ - Favicon
41
+ - Other site icons
42
+
43
+ ## Tracking (detected if present)
44
+
45
+ - Google Tag Manager
46
+ - Google Analytics 4
47
+ - Universal Analytics
48
+ - Matomo
49
+ - Facebook Pixel
50
+ - Plausible
51
+
52
+ ## Images
53
+
54
+ - Missing image alt text
55
+ - Empty image alt text
56
+ - Generic / unhelpful image alt text
57
+
58
+ ## Accessibility (static checks)
59
+
60
+ - Multiple h1 headings on one page
61
+ - Skipped heading levels
62
+ - Missing language on the page
63
+ - Form fields without a label
64
+ - Positive tabindex (keyboard focus order)
65
+
66
+ ## Security (secrets on the page)
67
+
68
+ - Leaked API keys / secrets in page HTML
69
+ - Leaked API keys / secrets in same-site JavaScript
70
+
71
+ ## Security headers (site-wide)
72
+
73
+ - HSTS (force HTTPS)
74
+ - Content Security Policy
75
+ - Clickjacking protection (X-Frame-Options or CSP)
76
+ - X-Content-Type-Options (nosniff)
77
+ - Referrer-Policy
78
+ - Permissions-Policy
79
+
80
+ ## Domain & redirects
81
+
82
+ - Domain redirect (e.g. apex → www)
83
+ - Redirect is permanent (301/308)
84
+ - Redirect target is reachable
85
+ - www and non-www both point to the same preferred host
86
+ - SPF (email authentication)
87
+ - DMARC (email authentication)
88
+
89
+ ## Search engines (robots & sitemap)
90
+
91
+ - robots.txt exists
92
+ - robots.txt is valid
93
+ - robots.txt does not block the whole site
94
+ - robots.txt lists a sitemap
95
+ - Sitemap exists and is reachable
96
+ - Sitemap is not empty
97
+ - Sitemap URLs match the pages found on the site
98
+ - Pages found on the site are listed in the sitemap
99
+
100
+ ## Agent readiness
101
+
102
+ - Content Signals in robots.txt (`ai-train` / `search` / `ai-input`)
103
+ - Explicit AI bot User-agent rules (e.g. GPTBot, ClaudeBot)
104
+ - llms.txt overview at `/llms.txt`
105
+ - Markdown content negotiation (`Accept: text/markdown`)
106
+ - Agent-useful Link response headers on the homepage
107
+ - Well-known protocol discovery (MCP, Agent Skills, API Catalog, ARD, A2A) — informational
108
+
109
+ ## Technology (informational)
110
+
111
+ - Platform / framework / CMS / hosting / CDN fingerprints
112
+
113
+ ## Note on redirect-only runs
114
+
115
+ If the start URL only redirects (for example a domain move), Flightcheck skips most
116
+ page checks and only covers redirects, DNS (SPF/DMARC), and the report.
@@ -0,0 +1,158 @@
1
+ # Flightcheck Crawler
2
+
3
+ This crawler collects per-URL verification data for SEO, metadata, tracking, and icons.
4
+
5
+ ## Purpose
6
+
7
+ - Crawl from a start URL; sitemap URLs are added as extra seeds by default so all pages from the sitemap are visited.
8
+ - Write incremental JSON output after each processed URL.
9
+ - Deduplicate on URL without query/hash.
10
+ - Exclude by URL and pathname.
11
+ - Safe throttling via concurrency, delay, and burst delay.
12
+
13
+ ## CLI usage
14
+
15
+ ```bash
16
+ pnpm run flightcheck -- https://example.com
17
+ ```
18
+
19
+ By default, flightcheck writes crawl JSON plus a structured analyze report to `./flightcheck/`,
20
+ with filenames based on timestamp and hostname, for example:
21
+
22
+ - `./flightcheck/20260618.1413-example.com-raw.json`
23
+ - `./flightcheck/20260618.1413-example.com-report.json`
24
+ - `./flightcheck/20260618.1413-example.com-report.md`
25
+
26
+ Use `--json-only` to skip the analyze report.
27
+
28
+ Key flags:
29
+
30
+ - `--output <file>` default `{timestamp}-{hostname}-raw.json` in `./flightcheck/`
31
+ - `--report <file>` default `{timestamp}-{hostname}-report.md` in `./flightcheck/`
32
+ (paired `*-report.json` is written next to it)
33
+ - `--json-only` write crawl JSON only; with `--json-only`, default checks fall back to `crawl` only
34
+ - `--errors-only` include only critical/error findings in the Markdown report
35
+ - `--checks <ids>` comma-separated checks; default: all implemented checks (`crawl`, `security-headers`, `dns`, `robots-txt`, `sitemap`, `analyze`)
36
+ - `--parallel` run independent checks in the same wave concurrently
37
+ - `--max-pages <n>`
38
+ - `--delay-ms <n>`
39
+ - `--timeout-ms <n>`
40
+ - `--concurrency <n>`
41
+ - `--burst-delay-ms <n>`
42
+ - `--sitemap-start` (legacy) limits initial seeds to sitemap URLs plus the start URL; by default sitemap URLs are already added to the crawl queue
43
+ - `--sitemap-url <url>`
44
+ - `--exclude <pattern1,pattern2>` (repeatable)
45
+ - `--respect-robots-txt`
46
+ - `--quiet` (suppress Crawlee info/statistics logs; warnings and errors only)
47
+ - `--only <groups>` run only these check groups (comma-separated)
48
+ - `--skip <groups>` skip these check groups (comma-separated)
49
+ - `--reveal-secrets` show full secret values instead of masked
50
+
51
+ Examples:
52
+
53
+ ```bash
54
+ pnpm run flightcheck -- https://example.com --max-pages 200 --concurrency 5 --delay-ms 100
55
+ pnpm run flightcheck -- https://example.com --sitemap-start
56
+ pnpm run flightcheck -- https://example.com --exclude "/search,/preview"
57
+ pnpm run flightcheck -- https://example.com --respect-robots-txt
58
+ pnpm run flightcheck -- https://example.com --quiet
59
+ pnpm run flightcheck -- https://example.com --only security
60
+ pnpm run flightcheck -- https://example.com --skip tracking,social
61
+ pnpm run flightcheck -- https://example.com --only security --reveal-secrets
62
+ ```
63
+
64
+ ## Check groups
65
+
66
+ Extraction is split into named groups. All groups run by default; with `--only` you run one or a
67
+ few, with `--skip` you exclude groups. `--only` and `--skip` cannot be used together.
68
+
69
+ - `meta` — title, h1, description, robots, template, metaTitle, charset, language,
70
+ viewport, doctype, canonical, color-scheme, theme-color, main landmark count.
71
+ - `icons` — favicon and icons.
72
+ - `social` — Open Graph and Twitter metadata.
73
+ - `tracking` — GTM, GA4, UA, Matomo, Facebook Pixel, Plausible.
74
+ - `stack` — technology fingerprints via curated rules (see [stack.md](./stack.md)).
75
+ - `security` — scan for leaked API keys and secrets (see below).
76
+ - `images` — extracts image-alt issues to `images.issues` (missing-alt,
77
+ empty-alt, generic-alt).
78
+ - `a11y-static` — static accessibility checks to `a11yStatic.issues`
79
+ (heading-skip, multiple-h1, missing-lang, unlabeled-input, positive-tabindex).
80
+
81
+ ### Sitemap parsing
82
+
83
+ `sitemap.xml` can be a **sitemap index** (`<sitemapindex>`) that points to child sitemap files
84
+ via nested `<loc>` entries, or a **urlset** with page URLs. The crawler follows sitemap
85
+ index files recursively and treats apex and `www` hostnames as the same site (so
86
+ `https://example.com/sitemap.xml` can discover URLs on `https://www.example.com/`).
87
+
88
+ The `security` group scans both page HTML and linked same-origin JavaScript files (`<script src>`)
89
+ for leaked API keys and secrets. Shared bundles are cached per URL and fetched only once.
90
+ Findings get a severity:
91
+
92
+ - `critical` — should never be in client code (AWS keys, Stripe secret keys, GitHub
93
+ tokens, private-key blocks, generic `secret`/`password` assignments).
94
+ - `review` — normal in client code but should be domain-/referrer-restricted
95
+ (Google API keys, Stripe publishable keys, generic `apiKey`/`token`).
96
+
97
+ The providers/patterns are: google-api-key (`google`), aws-access-key-id (`aws`),
98
+ stripe-secret-key and stripe-publishable-key (`stripe`), github-token (`github`),
99
+ private-key, generic-secret and generic-api-key (`generic`).
100
+
101
+ Secret values are masked by default (`AIzaSy…BC0Y`). The summary then shows a hint to
102
+ re-run with `--reveal-secrets` for full values.
103
+
104
+ When a group is skipped, the corresponding fields stay empty; the output structure never changes.
105
+
106
+ ## Output schema
107
+
108
+ Each record contains:
109
+
110
+ - URL and status
111
+ - H1/title/meta fields, including `template` (from `meta[name="template"]`) and `metaTitle`
112
+ - `mainCount` (number of `<main>` elements, `null` when meta group is skipped)
113
+ - canonical/favicon/icons
114
+ - OG and Twitter metadata
115
+ - tracking detection (GTM, GA4, UA, Matomo, Facebook Pixel, Plausible)
116
+ - `stack.detections` — technology fingerprints per page (aggregated in analyze)
117
+ - `security` with `secrets` (found keys/secrets) and `scannedAssets` (number of
118
+ scanned JS files)
119
+ - `images.issues` — image-alt issues (only when the `images` group runs)
120
+ - `a11yStatic.issues` — static a11y findings (only when the `a11y-static` group runs)
121
+ - optional `note` and `error`
122
+
123
+ Text fields are always filled with a string — no `undefined` or `null`.
124
+
125
+ Each `secrets` finding contains `type`, `provider`, `severity` (`critical` or
126
+ `review`), `masked` (masked or — with `--reveal-secrets` — full value) and
127
+ `source` (`html` or the URL of the JS file). The closing summary contains
128
+ `secretsFound` (total number of findings) and, with masked output and findings, a `hint`.
129
+
130
+ ## Architecture
131
+
132
+ The CLI runs via the checks layer (`runChecks` in `src/checks/runner.ts`), which drives the
133
+ crawler; `src/cli.ts` no longer calls `runCrawler` directly.
134
+ The checks layer plans checks in waves and delivers crawl and analyze output.
135
+
136
+ - Checks layer: `src/checks/runner.ts`, `src/checks/crawl.ts`, `src/checks/types.ts`
137
+ - Crawl layer: `src/crawler/runCrawler.ts`
138
+ - Extract layer: `src/crawler/extractors.ts`, `src/crawler/tier1Extractors.ts`,
139
+ `src/crawler/tracking.ts`, `src/crawler/secrets.ts` and `src/crawler/stack.ts`
140
+ - Report layer: `src/crawler/reporter.ts`
141
+
142
+ Additionally:
143
+
144
+ - URL normalization and excludes: `src/crawler/urlUtils.ts`
145
+ - Sitemap parsing: `src/crawler/sitemap.ts`
146
+ - CLI parsing: `src/cli.ts`
147
+
148
+ ## Behavior
149
+
150
+ - Only internal links are crawled. Links are discovered via `extractInternalLinks` and added to the queue; Crawlee's `enqueueLinks` is intentionally not used.
151
+ - Sitemap URLs are added to the crawl queue by default so pages from `sitemap.xml` are visited even when they are not reachable via internal links.
152
+ - `--max-pages` is the hard stop (`maxRequestsPerCrawl`). The crawl stops once this count is processed, even if unvisited links remain. Increase `--max-pages` to crawl the entire site.
153
+ - Query parameters and hashes do not count toward URL identity.
154
+ - Non-HTML responses are reported with `note`.
155
+ - Links to files with a known non-HTML extension (such as `.pdf`, `.zip`, images, video, fonts) are not added to the queue, so Crawlee does not generate unnecessary retries and errors.
156
+ - With `--respect-robots-txt`, URLs excluded by `robots.txt` are skipped.
157
+ - After each URL, output is written atomically.
158
+ - On `SIGINT`, the crawl stops gracefully while preserving partial output.
package/docs/index.md ADDED
@@ -0,0 +1,24 @@
1
+ # Documentation index
2
+
3
+ ## Features
4
+
5
+ - [What Flightcheck checks](./checks.md)
6
+ - [Check API](./check-api.md)
7
+ - [Agent readiness](./agent-ready.md)
8
+ - [Analyze reports](./analyze.md)
9
+ - [Crawler](./crawler.md)
10
+ - [Stack detection](./stack.md)
11
+ - [QC checks plan](./qc-checks-plan.md)
12
+ - [Agent fixes (deprecated)](./agent-fixes.md)
13
+
14
+ ## Specs
15
+
16
+ - [Structured report](./superpowers/specs/2026-10-27-structured-report-design.md)
17
+
18
+ ## Changelog
19
+
20
+ - Package releases: [CHANGELOG.md](../CHANGELOG.md)
21
+ - Branch notes: [changelog/](./changelog/)
22
+ - [2026-10-27 — npm-public-package](./changelog/2026-10-27--npm-public-package.md)
23
+ - [2026-10-27 — structured-report-json](./changelog/2026-10-27--structured-report-json.md)
24
+ - [2026-09-28 — agent-ready-check](./changelog/2026-09-28--agent-ready-check.md)