@crawlcheck/sdk 1.0.4 → 1.0.5

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.
@@ -105,32 +105,33 @@ export interface paths {
105
105
  patch?: never;
106
106
  trace?: never;
107
107
  };
108
- "/api/v1/changes": {
108
+ "/api/v1/visitor": {
109
109
  parameters: {
110
110
  query?: never;
111
111
  header?: never;
112
112
  path?: never;
113
113
  cookie?: never;
114
114
  };
115
- /** What moved: one event per resolve-answer section that changed when an answer was rebuilt (crawl_policy, delivery, machine_files, capabilities, entity, findings). ?since=<ISO time>, ?domain= for one domain's history, ?limit= up to 500. Re-resolve only the domains listed */
116
- get: operations["resolveChangesV1"];
115
+ /** Visitor Resolve: is this request really from the agent its user agent names? ?ip=&ua= returns verified (inside the operator's published ranges), spoofed, unverifiable or not_a_known_agent. Nothing about the visitor is stored */
116
+ get: operations["visitorResolveV1"];
117
117
  put?: never;
118
- post?: never;
118
+ /** Visitor Resolve for 1-100 requests at once: {visitors: [{ip, ua}]} */
119
+ post: operations["visitorResolveBatchV1"];
119
120
  delete?: never;
120
121
  options?: never;
121
122
  head?: never;
122
123
  patch?: never;
123
124
  trace?: never;
124
125
  };
125
- "/api/mcp/servers": {
126
+ "/api/v1/conduct": {
126
127
  parameters: {
127
128
  query?: never;
128
129
  header?: never;
129
130
  path?: never;
130
131
  cookie?: never;
131
132
  };
132
- /** Remote MCP servers the official MCP Registry lists on a domain, each with what its endpoint answered to the MCP handshake (initialize + tools/list; no tool is ever called): outcome, protocol version, tool count, tool-list hash and drift. Public */
133
- get: operations["mcpServersForHost"];
133
+ /** Agent conduct record: for every verifiable agent, what it did on crawlcheck.io (verified by source address) - robots.txt respected or disallowed paths fetched, peak requests per minute against the site limit, conditional requests - plus how often its name is forged and what sites found when they checked visitors claiming it. Signed */
134
+ get: operations["conductV1"];
134
135
  put?: never;
135
136
  post?: never;
136
137
  delete?: never;
@@ -139,15 +140,15 @@ export interface paths {
139
140
  patch?: never;
140
141
  trace?: never;
141
142
  };
142
- "/api/mcp/index": {
143
+ "/api/v1/conduct/{agent}": {
143
144
  parameters: {
144
145
  query?: never;
145
146
  header?: never;
146
147
  path?: never;
147
148
  cookie?: never;
148
149
  };
149
- /** The MCP Registry import and observation cycle: servers imported, endpoints observed this cycle by outcome (initialized, auth_required, unreachable, ...), tool-list drift, the most recent observations. Public */
150
- get: operations["mcpIndex"];
150
+ /** The conduct record for one agent, e.g. GPTBot, signed on its own */
151
+ get: operations["conductAgentV1"];
151
152
  put?: never;
152
153
  post?: never;
153
154
  delete?: never;
@@ -156,67 +157,68 @@ export interface paths {
156
157
  patch?: never;
157
158
  trace?: never;
158
159
  };
159
- "/api/v1/preflight": {
160
+ "/api/v1/mcp/lock": {
160
161
  parameters: {
161
162
  query?: never;
162
163
  header?: never;
163
164
  path?: never;
164
165
  cookie?: never;
165
166
  };
166
- get?: never;
167
+ /** Make an MCP tool lockfile for a server (?url=): handshake and tools/list only; per-tool SHA-256 of {name, description, inputSchema, annotations} and a list hash. Signed (crawlcheck-mcp-lock). Spec /spec/mcp-lockfile */
168
+ get: operations["mcpLockUrl"];
167
169
  put?: never;
168
- /** The policy engine: before an action, POST {domain, action (read|cite|connect|transact|administer), agent?, template?, policy?} and receive a signed decision receipt (allow | warn | require_confirmation | block | unsupported) bound to the resolve answer it was made from. When the decision is not allow, alternatives[] names what to do instead (rescan, a machine file, a corroborated profile, an MCP endpoint that completed the handshake, human review), each from CrawlCheck’s own observations. A policy can only make the decision stricter. Templates: safe_citation, safe_data_retrieval, safe_api_connect, safe_mcp_tool, safe_commerce, safe_oauth, support_escalation */
169
- post: operations["preflightV1"];
170
+ /** Make a lockfile from a tools/list result you hold ({tools:[...], url?}) or a server URL ({url}) */
171
+ post: operations["mcpLockTools"];
170
172
  delete?: never;
171
173
  options?: never;
172
174
  head?: never;
173
175
  patch?: never;
174
176
  trace?: never;
175
177
  };
176
- "/api/v1/resolve": {
178
+ "/api/v1/mcp/lock/check": {
177
179
  parameters: {
178
180
  query?: never;
179
181
  header?: never;
180
182
  path?: never;
181
183
  cookie?: never;
182
184
  };
183
- /** Before acting on a domain: one signed answer. Crawler policy as declared (robots.txt per crawler), delivery as observed per identity, machine files, capabilities with policy classes and certificate, entity reciprocity and the open findings (top one in full without a licence), each section declared/observed/not_measured with its time. No overall score. An unknown domain answers not_measured and a measurement is requested */
184
- get: operations["resolveDomainV1"];
185
+ get?: never;
185
186
  put?: never;
186
- /** Batch resolve: POST {domains:[..]} (1-100) and receive each domain's signed ResolveV1 answer in one response */
187
- post: operations["resolveBatchV1"];
187
+ /** Compare a lockfile with the server's current tools ({lock, tools} or {lock, url}): verdict unchanged | changed | unreachable, decision connect | block, tools added, removed and modified, the description text that moved. Signed (crawlcheck-mcp-lock-check) */
188
+ post: operations["mcpLockCheck"];
188
189
  delete?: never;
189
190
  options?: never;
190
191
  head?: never;
191
192
  patch?: never;
192
193
  trace?: never;
193
194
  };
194
- "/schemas/resolve.json": {
195
+ "/api/v1/mcp/scan": {
195
196
  parameters: {
196
197
  query?: never;
197
198
  header?: never;
198
199
  path?: never;
199
200
  cookie?: never;
200
201
  };
201
- /** JSON Schema (2020-12) for the /api/v1/resolve answer */
202
- get: operations["resolveSchema"];
202
+ /** Tool-poisoning scan of a remote MCP server (?url=): handshake and tools/list only, no tool is called; every tool text checked for hidden characters, instructions aimed at the model, requests for secrets or the conversation, and instructions about other tools. Signed */
203
+ get: operations["mcpScanUrl"];
203
204
  put?: never;
204
- post?: never;
205
+ /** The same scan over a tools/list result you send ({tools:[...]}, up to 300) or a server URL ({url}). Signed */
206
+ post: operations["mcpScanTools"];
205
207
  delete?: never;
206
208
  options?: never;
207
209
  head?: never;
208
210
  patch?: never;
209
211
  trace?: never;
210
212
  };
211
- "/api/v1/machine-record": {
213
+ "/api/v1/rights-feed": {
212
214
  parameters: {
213
215
  query?: never;
214
216
  header?: never;
215
217
  path?: never;
216
218
  cookie?: never;
217
219
  };
218
- /** The unified machine record for one observation: subject, grade, findings (top one in full without a licence), capabilities with verification, evidence roots and verifier links */
219
- get: operations["getMachineRecordV1"];
220
+ /** Rights feed for crawler operators: the index of signed weekly editions covering the top 10,000 sites (per site: robots.txt groups to apply to any URL with your own token, Content-Signal, TDM-Rep, ai.txt, page directives, terms AI clauses, and the answer per use at the root); latest edition, the one being built, totals per use. Spec at /spec/rights-feed */
221
+ get: operations["rightsFeedIndex"];
220
222
  put?: never;
221
223
  post?: never;
222
224
  delete?: never;
@@ -225,15 +227,15 @@ export interface paths {
225
227
  patch?: never;
226
228
  trace?: never;
227
229
  };
228
- "/api/fix/cache": {
230
+ "/api/v1/rights-feed/{id}/{file}": {
229
231
  parameters: {
230
232
  query?: never;
231
233
  header?: never;
232
234
  path?: never;
233
235
  cookie?: never;
234
236
  };
235
- /** STALE_CACHE_SERVED fix plan: the homepage fetched now, its Age, the cache layers in purge order (innermost first), the declared HTML lifetime, a fresh-read comparison, and whether a purge clears the finding and keeps it cleared */
236
- get: operations["fixStaleCache"];
237
+ /** One file of a finished rights-feed edition: manifest.json (signed crawlcheck-rights-feed: parts with sha256 and counts) or part-NNNN.ndjson.gz (one signed crawlcheck-rights line per site) */
238
+ get: operations["rightsFeedFile"];
237
239
  put?: never;
238
240
  post?: never;
239
241
  delete?: never;
@@ -242,15 +244,15 @@ export interface paths {
242
244
  patch?: never;
243
245
  trace?: never;
244
246
  };
245
- "/api/fix/chain": {
247
+ "/api/v1/rights": {
246
248
  parameters: {
247
249
  query?: never;
248
250
  header?: never;
249
251
  path?: never;
250
252
  cookie?: never;
251
253
  };
252
- /** MACHINE_CHAIN_HEAVY fix plan: the files read before the page and the absent-file 404s, measured reductions with the chain size after each, and the step at which the detector stops firing */
253
- get: operations["fixMachineChain"];
254
+ /** Rights Resolve: one permission answer per use (train, ground, summarize, cite, transact) for a domain and path, merged from robots.txt (the agent's own RFC 9309 group), Content-Signal, ai.txt, TDM-Rep, robots meta, X-Robots-Tag and the terms page; every value names the signal, URL and line or clause that decided it, with the conflicts. Signed */
255
+ get: operations["rightsV1"];
254
256
  put?: never;
255
257
  post?: never;
256
258
  delete?: never;
@@ -259,15 +261,15 @@ export interface paths {
259
261
  patch?: never;
260
262
  trace?: never;
261
263
  };
262
- "/api/fix/code": {
264
+ "/api/v1/read-equivalence": {
263
265
  parameters: {
264
266
  query?: never;
265
267
  header?: never;
266
268
  path?: never;
267
269
  cookie?: never;
268
270
  };
269
- /** PAGE_IS_MOSTLY_CODE fix plan: the measured byte breakdown, ordered steps with the ratio after each, the step at which the detector stops firing, or the markup/text change needed when moving code cannot clear it */
270
- get: operations["fixMostlyCode"];
271
+ /** Read-equivalence certificate for one URL: the main text served to GPTBot, ClaudeBot and PerplexityBot compared word by word with what a browser receives at the same moment; verdict per identity with the diff ratio and the sentences only one side received. Signed */
272
+ get: operations["readEquivalenceV1"];
271
273
  put?: never;
272
274
  post?: never;
273
275
  delete?: never;
@@ -276,15 +278,15 @@ export interface paths {
276
278
  patch?: never;
277
279
  trace?: never;
278
280
  };
279
- "/api/corroboration": {
281
+ "/api/v1/claims": {
280
282
  parameters: {
281
283
  query?: never;
282
284
  header?: never;
283
285
  path?: never;
284
286
  cookie?: never;
285
287
  };
286
- /** Each observer's reading of the identity-dependent findings side by side (primary Worker vs the independent second observer), with a corroboration status per finding */
287
- get: operations["getCorroboration"];
288
+ /** Self-claim ledger: what a site says about itself (telephone, email, address, hours, prices, refund window, founded, years in business, API rate limits) from its own pages, each value with first_seen and last_seen, plus the claim changes CrawlCheck recorded. Signed */
289
+ get: operations["selfClaimsV1"];
288
290
  put?: never;
289
291
  post?: never;
290
292
  delete?: never;
@@ -293,117 +295,118 @@ export interface paths {
293
295
  patch?: never;
294
296
  trace?: never;
295
297
  };
296
- "/api/explain": {
298
+ "/api/v1/origin": {
297
299
  parameters: {
298
300
  query?: never;
299
301
  header?: never;
300
302
  path?: never;
301
303
  cookie?: never;
302
304
  };
303
- /** One finding explained: rule and revision, compared fetches, valid time, Merkle proof of the decision in the signed manifest */
304
- get: operations["explainFinding"];
305
+ /** Canonical origin for an anchored passage (?passage=<anchor id>): which page published it first and which carry copies, from the copies' rel=canonical, Internet Archive first captures, declared dates and CrawlCheck's own sightings. Signed */
306
+ get: operations["originByAnchorV1"];
305
307
  put?: never;
306
- post?: never;
308
+ /** Canonical origin for {text, urls[]} (up to 8 pages): the same decision for any passage and set of pages; pages a copy names as canonical are added automatically */
309
+ post: operations["originV1"];
307
310
  delete?: never;
308
311
  options?: never;
309
312
  head?: never;
310
313
  patch?: never;
311
314
  trace?: never;
312
315
  };
313
- "/api/observe/enroll": {
316
+ "/api/v1/content-clock": {
314
317
  parameters: {
315
318
  query?: never;
316
319
  header?: never;
317
320
  path?: never;
318
321
  cookie?: never;
319
322
  };
320
- get?: never;
323
+ /** Content-change clock for a page: a hash of its main content (chrome, ads, cookie banners and scripts removed; dates, times and tokens masked), when that content was first seen, the bounds of the last observed change, and what the page itself declares (Last-Modified, dateModified, article:modified_time) with whether the two agree. Read at most every 10 minutes; signed */
324
+ get: operations["contentClockV1"];
321
325
  put?: never;
322
- /** Enrol an independent observer (open observer protocol v1): an Ed25519 key, an id ind:<name>, operator and network, signed with the key it enrols; the id is bound to the first key that claims it */
323
- post: operations["enrolObserver"];
326
+ post?: never;
324
327
  delete?: never;
325
328
  options?: never;
326
329
  head?: never;
327
330
  patch?: never;
328
331
  trace?: never;
329
332
  };
330
- "/api/observe/check": {
333
+ "/api/v1/cited-by": {
331
334
  parameters: {
332
335
  query?: never;
333
336
  header?: never;
334
337
  path?: never;
335
338
  cookie?: never;
336
339
  };
337
- get?: never;
340
+ /** The cited-by index: for ?url= a page or ?domain= a site, how often agents cited it through CrawlCheck (citation anchors, cite preflights), by how many distinct citing networks, how many distinct passages, and whether the quoted text is still on the page (latest recheck per anchor). Citer counts and agent names withheld below 3 citing networks */
341
+ get: operations["citedByV1"];
338
342
  put?: never;
339
- /** Run the Worker's own checks on an observation or enrolment without storing it: shape, key against the directory entry (the live directory, or one you send), signature. The fixtures at /observer/fixtures.json run against it */
340
- post: operations["checkObservation"];
343
+ post?: never;
341
344
  delete?: never;
342
345
  options?: never;
343
346
  head?: never;
344
347
  patch?: never;
345
348
  trace?: never;
346
349
  };
347
- "/api/data/inventory": {
350
+ "/api/v1/anchor": {
348
351
  parameters: {
349
352
  query?: never;
350
353
  header?: never;
351
354
  path?: never;
352
355
  cookie?: never;
353
356
  };
354
- /** Everything held about a domain, signed: each family of stored keys with counts and bytes, what is kept after deletion and why. Licence for the domain or owner */
355
- get: operations["dataInventory"];
357
+ get?: never;
356
358
  put?: never;
357
- post?: never;
359
+ /** Citation notarization: {url, text} fetches the page, finds the quoted passage in its visible text and returns a signed anchor (URL, text-fragment selector, passage hash, page text hash, time) that also joins the day's OpenTimestamps-anchored Merkle seal. 422 when the passage is not on the page. 30 per hour per address */
360
+ post: operations["anchorCreateV1"];
358
361
  delete?: never;
359
362
  options?: never;
360
363
  head?: never;
361
364
  patch?: never;
362
365
  trace?: never;
363
366
  };
364
- "/api/data/export": {
367
+ "/api/v1/anchor/{id}/watch": {
365
368
  parameters: {
366
369
  query?: never;
367
370
  header?: never;
368
371
  path?: never;
369
372
  cookie?: never;
370
373
  };
371
- /** Export everything held about a domain in signed parts: part 0 = the inventory and every stored row; then archived records with the bytes each fetch received; then receipts, dispute resolutions and observations */
372
- get: operations["dataExport"];
374
+ get?: never;
373
375
  put?: never;
374
- post?: never;
376
+ /** Correction propagation: {webhook} (https, public host). The anchor is rechecked every 15 minutes; when its status changes (present / no_longer_present / page_unreachable, the last only after two failed checks) the webhook receives a signed crawlcheck-anchor-check with previous_status. Up to 5 webhooks per anchor; POST /api/v1/anchor also takes webhook */
377
+ post: operations["anchorWatchV1"];
375
378
  delete?: never;
376
379
  options?: never;
377
380
  head?: never;
378
381
  patch?: never;
379
382
  trace?: never;
380
383
  };
381
- "/api/data/delete": {
384
+ "/api/v1/anchor/sink/{token}": {
382
385
  parameters: {
383
386
  query?: never;
384
387
  header?: never;
385
388
  path?: never;
386
389
  cookie?: never;
387
390
  };
388
- get?: never;
391
+ /** A test webhook: use https://crawlcheck.io/api/v1/anchor/sink/<token> as a webhook and read the last 10 deliveries here (kept one day) */
392
+ get: operations["anchorSinkV1"];
389
393
  put?: never;
390
- /** Delete everything held about a domain: {domain, confirm: domain, inventory_sha256} starts a job (an inventory issued in the last 24 hours is required); POST {job} continues it. Ends in a signed deletion record */
391
- post: operations["dataDelete"];
394
+ post?: never;
392
395
  delete?: never;
393
396
  options?: never;
394
397
  head?: never;
395
398
  patch?: never;
396
399
  trace?: never;
397
400
  };
398
- "/api/data/deletion": {
401
+ "/api/v1/anchor/{id}": {
399
402
  parameters: {
400
403
  query?: never;
401
404
  header?: never;
402
405
  path?: never;
403
406
  cookie?: never;
404
407
  };
405
- /** A signed deletion record: counts per family and the digest of the deleted-key list, never the data */
406
- get: operations["dataDeletionRecord"];
408
+ /** An anchor and its seal state. ?recheck=1 refetches the page and returns a signed crawlcheck-anchor-check: present, no_longer_present or page_unreachable. A passage edited away is no_longer_present, never false */
409
+ get: operations["anchorGetV1"];
407
410
  put?: never;
408
411
  post?: never;
409
412
  delete?: never;
@@ -412,15 +415,15 @@ export interface paths {
412
415
  patch?: never;
413
416
  trace?: never;
414
417
  };
415
- "/api/trace/coverage": {
418
+ "/api/v1/visitor/arrival": {
416
419
  parameters: {
417
420
  query?: never;
418
421
  header?: never;
419
422
  path?: never;
420
423
  cookie?: never;
421
424
  };
422
- /** Trace coverage: per scan, how many findings and claims link their own rule span, how many stage errors name a span, broken parent links, malformed or duplicate ids, dropped spans. ?id= one record (counts public; unlinked codes with a licence); without id the last 300 scans and the latest CI result */
423
- get: operations["traceCoverage"];
425
+ /** A site's own Cloudflare Worker reports one agent request (ua, path, verdict) after answering it; the site is proven by the CF-Worker header Cloudflare sets on Worker subrequests. Counts toward the Agent Traffic Index and the network figures on /data. 403 from anything that is not a Worker subrequest */
426
+ get: operations["visitorArrivalV1"];
424
427
  put?: never;
425
428
  post?: never;
426
429
  delete?: never;
@@ -429,68 +432,66 @@ export interface paths {
429
432
  patch?: never;
430
433
  trace?: never;
431
434
  };
432
- "/api/trace/ci": {
435
+ "/api/v1/traffic-index": {
433
436
  parameters: {
434
437
  query?: never;
435
438
  header?: never;
436
439
  path?: never;
437
440
  cookie?: never;
438
441
  };
439
- /** The latest trace CI result (schema violations, broken parent links, unlinked findings) and its history */
440
- get: operations["traceCiResult"];
442
+ /** The Agent Traffic Index, month to date: per agent, how many reporting sites it visited, fetches, verified / forged / unverifiable by source address, machine-file share. Agent rows only above a 5-site floor; no site named. Signed */
443
+ get: operations["trafficIndexV1"];
441
444
  put?: never;
442
- /** Callable only by this repository's trace workflow (GitHub OIDC, audience crawlcheck-trace): phase sample returns real traces (TraceV1) to validate; phase report stores the verdict */
443
- post: operations["traceCi"];
445
+ post?: never;
444
446
  delete?: never;
445
447
  options?: never;
446
448
  head?: never;
447
449
  patch?: never;
448
450
  trace?: never;
449
451
  };
450
- "/api/disputes": {
452
+ "/api/v1/traffic-index/{month}": {
451
453
  parameters: {
452
454
  query?: never;
453
455
  header?: never;
454
456
  path?: never;
455
457
  cookie?: never;
456
458
  };
457
- /** The dispute and correction ledger: every dispute filed against a finding, its state and verdict. ?id=dsp1:… returns one dispute with its readings and events; ?domain= filters */
458
- get: operations["disputeLedger"];
459
+ /** A monthly edition of the Agent Traffic Index (YYYY-MM). Complete months are final and signed once */
460
+ get: operations["trafficIndexMonthV1"];
459
461
  put?: never;
460
- /** File a dispute against one finding on one record: {report_id, code, path?, ground: misread|fixed|network|rule, statement}. Accepted at once with a licence for the domain or the owner session; otherwise answers 202 with a token to serve at /.well-known/crawlcheck-dispute.txt */
461
- post: operations["fileDispute"];
462
+ post?: never;
462
463
  delete?: never;
463
464
  options?: never;
464
465
  head?: never;
465
466
  patch?: never;
466
467
  trace?: never;
467
468
  };
468
- "/api/disputes/confirm": {
469
+ "/api/v1/visitor/stats": {
469
470
  parameters: {
470
471
  query?: never;
471
472
  header?: never;
472
473
  path?: never;
473
474
  cookie?: never;
474
475
  };
475
- get?: never;
476
+ /** Daily counts of visitor checks for the last 14 days, by verdict and claimed agent. Counts only */
477
+ get: operations["visitorStatsV1"];
476
478
  put?: never;
477
- /** After serving the token at https://<domain>/.well-known/crawlcheck-dispute.txt, accept the dispute */
478
- post: operations["confirmDisputeOwnership"];
479
+ post?: never;
479
480
  delete?: never;
480
481
  options?: never;
481
482
  head?: never;
482
483
  patch?: never;
483
484
  trace?: never;
484
485
  };
485
- "/api/disputes/resolution": {
486
+ "/api/v1/decisions/{sha256}": {
486
487
  parameters: {
487
488
  query?: never;
488
489
  header?: never;
489
490
  path?: never;
490
491
  cookie?: never;
491
492
  };
492
- /** A signed dispute resolution (machine record). Verify offline: node crawlcheck-verify.mjs resolution.json */
493
- get: operations["getDisputeResolution"];
493
+ /** Check a CrawlCheck-Receipt header: a site sends the decision receipt digest it received (and ?host= its own host) and gets accept plus the checks behind it (host matches, not expired, decision allow or warn) and the full signed receipt. Receipts are held until a day after they expire */
494
+ get: operations["decisionCheckV1"];
494
495
  put?: never;
495
496
  post?: never;
496
497
  delete?: never;
@@ -499,33 +500,32 @@ export interface paths {
499
500
  patch?: never;
500
501
  trace?: never;
501
502
  };
502
- "/api/disputes/verify": {
503
+ "/api/v1/decisions": {
503
504
  parameters: {
504
505
  query?: never;
505
506
  header?: never;
506
507
  path?: never;
507
508
  cookie?: never;
508
509
  };
509
- /** Check a stored resolution server side: hash, key id, key published, signature, verdict re-derived, readings after the dispute */
510
- get: operations["verifyDisputeResolution"];
510
+ /** Daily counts for the last 14 days: preflight decisions issued, and CrawlCheck-Receipt headers checked by sites (found, accepted, by decision and action). Counts only */
511
+ get: operations["decisionStatsV1"];
511
512
  put?: never;
512
- /** Check a resolution you hold */
513
- post: operations["verifyDisputeResolutionPost"];
513
+ post?: never;
514
514
  delete?: never;
515
515
  options?: never;
516
516
  head?: never;
517
517
  patch?: never;
518
518
  trace?: never;
519
519
  };
520
- "/api/datasets": {
520
+ "/api/v1/resolve-prefix/{prefix}": {
521
521
  parameters: {
522
522
  query?: never;
523
523
  header?: never;
524
524
  path?: never;
525
525
  cookie?: never;
526
526
  };
527
- /** The dataset catalogue: counts per lane and day, the latest day's breakdown, the field dictionary and the technology list. Public */
528
- get: operations["datasetCatalogue"];
527
+ /** Private lookup: send 2-8 hex characters of sha256(domain) and receive every measured domain's signed ResolveV1 answer in that bucket, so the domain you are about to act on is never sent. Pick your match locally */
528
+ get: operations["resolvePrefixV1"];
529
529
  put?: never;
530
530
  post?: never;
531
531
  delete?: never;
@@ -534,15 +534,15 @@ export interface paths {
534
534
  patch?: never;
535
535
  trace?: never;
536
536
  };
537
- "/api/datasets/sample": {
537
+ "/api/v1/snapshot": {
538
538
  parameters: {
539
539
  query?: never;
540
540
  header?: never;
541
541
  path?: never;
542
542
  cookie?: never;
543
543
  };
544
- /** 25 measured rows from the latest files. Public */
545
- get: operations["datasetSample"];
544
+ /** The daily signed snapshot of every public Resolve answer: the latest manifest, the snapshot in progress, and the finished snapshots kept (newest 7). CC BY 4.0, no key */
545
+ get: operations["resolveSnapshotIndex"];
546
546
  put?: never;
547
547
  post?: never;
548
548
  delete?: never;
@@ -551,15 +551,15 @@ export interface paths {
551
551
  patch?: never;
552
552
  trace?: never;
553
553
  };
554
- "/api/datasets/file": {
554
+ "/api/v1/snapshot/{id}/{file}": {
555
555
  parameters: {
556
556
  query?: never;
557
557
  header?: never;
558
558
  path?: never;
559
559
  cookie?: never;
560
560
  };
561
- /** One lane's file for one day, CSV or NDJSON, filterable. Needs a licence key with dataset access */
562
- get: operations["datasetFile"];
561
+ /** One file of a finished snapshot: manifest.json (signed crawlcheck-snapshot: parts with sha256 and record counts) or part-NNNN.ndjson.gz (gzip NDJSON, one signed ResolveV1 answer per line). Immutable once published */
562
+ get: operations["resolveSnapshotFile"];
563
563
  put?: never;
564
564
  post?: never;
565
565
  delete?: never;
@@ -568,15 +568,15 @@ export interface paths {
568
568
  patch?: never;
569
569
  trace?: never;
570
570
  };
571
- "/api/datasets/state": {
571
+ "/api/v1/changes": {
572
572
  parameters: {
573
573
  query?: never;
574
574
  header?: never;
575
575
  path?: never;
576
576
  cookie?: never;
577
577
  };
578
- /** One US state's local businesses across every day it was scanned. Needs a key with the local lane */
579
- get: operations["datasetState"];
578
+ /** What moved: one event per resolve-answer section that changed when an answer was rebuilt (crawl_policy, delivery, machine_files, capabilities, entity, findings). ?since=<ISO time>, ?domain= for one domain's history, ?limit= up to 500. Re-resolve only the domains listed */
579
+ get: operations["resolveChangesV1"];
580
580
  put?: never;
581
581
  post?: never;
582
582
  delete?: never;
@@ -585,32 +585,32 @@ export interface paths {
585
585
  patch?: never;
586
586
  trace?: never;
587
587
  };
588
- "/api/datasets/request": {
588
+ "/api/mcp/servers": {
589
589
  parameters: {
590
590
  query?: never;
591
591
  header?: never;
592
592
  path?: never;
593
593
  cookie?: never;
594
594
  };
595
- get?: never;
595
+ /** Remote MCP servers the official MCP Registry lists on a domain, each with what its endpoint answered to the MCP handshake (initialize + tools/list; no tool is ever called): outcome, protocol version, tool count, tool-list hash and drift. Public */
596
+ get: operations["mcpServersForHost"];
596
597
  put?: never;
597
- /** Ask for dataset access. Public, one request a minute per address */
598
- post: operations["datasetRequest"];
598
+ post?: never;
599
599
  delete?: never;
600
600
  options?: never;
601
601
  head?: never;
602
602
  patch?: never;
603
603
  trace?: never;
604
604
  };
605
- "/api/lanes": {
605
+ "/api/mcp/index": {
606
606
  parameters: {
607
607
  query?: never;
608
608
  header?: never;
609
609
  path?: never;
610
610
  cookie?: never;
611
611
  };
612
- /** The day's scan lanes and their quotas (SaaS 5,000, government and education 2,500, one US state's local businesses 5,000): measured, unmeasured, kinds detected, the state in rotation. Public */
613
- get: operations["scanLanes"];
612
+ /** The MCP Registry import and observation cycle: servers imported, endpoints observed this cycle by outcome (initialized, auth_required, unreachable, ...), tool-list drift, the most recent observations. Public */
613
+ get: operations["mcpIndex"];
614
614
  put?: never;
615
615
  post?: never;
616
616
  delete?: never;
@@ -619,49 +619,50 @@ export interface paths {
619
619
  patch?: never;
620
620
  trace?: never;
621
621
  };
622
- "/api/census": {
622
+ "/api/v1/preflight": {
623
623
  parameters: {
624
624
  query?: never;
625
625
  header?: never;
626
626
  path?: never;
627
627
  cookie?: never;
628
628
  };
629
- /** The agentic-web census: the frame (a frozen Tranco top-1,000 list), every run, the latest figures with their denominators, and the change since the first run (percentage points and sites that gained or lost each property). Public */
630
- get: operations["agenticWebCensus"];
629
+ get?: never;
631
630
  put?: never;
632
- post?: never;
631
+ /** The policy engine: before an action, POST {domain, action (read|cite|connect|transact|administer), agent?, template?, policy?} and receive a signed decision receipt (allow | warn | require_confirmation | block | unsupported) bound to the resolve answer it was made from. When the decision is not allow, alternatives[] names what to do instead (rescan, a machine file, a corroborated profile, an MCP endpoint that completed the handshake, human review), each from CrawlCheck’s own observations. A policy can only make the decision stricter. Templates: safe_citation, safe_data_retrieval, safe_api_connect, safe_mcp_tool, safe_commerce, safe_oauth, support_escalation */
632
+ post: operations["preflightV1"];
633
633
  delete?: never;
634
634
  options?: never;
635
635
  head?: never;
636
636
  patch?: never;
637
637
  trace?: never;
638
638
  };
639
- "/api/census/records": {
639
+ "/api/v1/resolve": {
640
640
  parameters: {
641
641
  query?: never;
642
642
  header?: never;
643
643
  path?: never;
644
644
  cookie?: never;
645
645
  };
646
- /** One run's per-site records in frame order: the raw readings (statuses, sizes, SHA-256 of what each identity was served, the robots.txt text, each machine file) and the derived fields every figure counts */
647
- get: operations["censusRecords"];
646
+ /** Before acting on a domain: one signed answer. Crawler policy as declared (robots.txt per crawler), delivery as observed per identity, machine files, capabilities with policy classes and certificate, entity reciprocity and the open findings (top one in full without a licence), each section declared/observed/not_measured with its time. No overall score. An unknown domain answers not_measured and a measurement is requested */
647
+ get: operations["resolveDomainV1"];
648
648
  put?: never;
649
- post?: never;
649
+ /** Batch resolve: POST {domains:[..]} (1-100) and receive each domain's signed ResolveV1 answer in one response */
650
+ post: operations["resolveBatchV1"];
650
651
  delete?: never;
651
652
  options?: never;
652
653
  head?: never;
653
654
  patch?: never;
654
655
  trace?: never;
655
656
  };
656
- "/api/census/frame": {
657
+ "/schemas/resolve.json": {
657
658
  parameters: {
658
659
  query?: never;
659
660
  header?: never;
660
661
  path?: never;
661
662
  cookie?: never;
662
663
  };
663
- /** The census sampling frame: the Tranco list id and configuration, the members measured, and the counts excluded by the publish filter and by opt-out */
664
- get: operations["censusFrame"];
664
+ /** JSON Schema (2020-12) for the /api/v1/resolve answer */
665
+ get: operations["resolveSchema"];
665
666
  put?: never;
666
667
  post?: never;
667
668
  delete?: never;
@@ -670,15 +671,15 @@ export interface paths {
670
671
  patch?: never;
671
672
  trace?: never;
672
673
  };
673
- "/api/registry/capabilities": {
674
+ "/api/v1/machine-record": {
674
675
  parameters: {
675
676
  query?: never;
676
677
  header?: never;
677
678
  path?: never;
678
679
  cookie?: never;
679
680
  };
680
- /** The capability registry: every measured site that declares agent capabilities, with counts by invocation policy class; ?domain= returns one site's capabilities declared beside observed, its mismatches and its signed capability certificate. Public */
681
- get: operations["capabilityRegistry"];
681
+ /** The unified machine record for one observation: subject, grade, findings (top one in full without a licence), capabilities with verification, evidence roots and verifier links */
682
+ get: operations["getMachineRecordV1"];
682
683
  put?: never;
683
684
  post?: never;
684
685
  delete?: never;
@@ -687,33 +688,32 @@ export interface paths {
687
688
  patch?: never;
688
689
  trace?: never;
689
690
  };
690
- "/api/registry/capabilities/verify": {
691
+ "/api/fix/cache": {
691
692
  parameters: {
692
693
  query?: never;
693
694
  header?: never;
694
695
  path?: never;
695
696
  cookie?: never;
696
697
  };
697
- /** Recompute a site's capability certificate from its stored record and verify it: hash, key id, published key, Ed25519 signature */
698
- get: operations["verifyCapabilityCertificate"];
698
+ /** STALE_CACHE_SERVED fix plan: the homepage fetched now, its Age, the cache layers in purge order (innermost first), the declared HTML lifetime, a fresh-read comparison, and whether a purge clears the finding and keeps it cleared */
699
+ get: operations["fixStaleCache"];
699
700
  put?: never;
700
- /** Verify a capability certificate you hold (the JSON from /api/registry/capabilities?domain=) */
701
- post: operations["verifyCapabilityCertificatePost"];
701
+ post?: never;
702
702
  delete?: never;
703
703
  options?: never;
704
704
  head?: never;
705
705
  patch?: never;
706
706
  trace?: never;
707
707
  };
708
- "/registry/capabilities/feed.json": {
708
+ "/api/fix/chain": {
709
709
  parameters: {
710
710
  query?: never;
711
711
  header?: never;
712
712
  path?: never;
713
713
  cookie?: never;
714
714
  };
715
- /** The capability registry as a JSON Feed 1.1: one item per site, updated when it is measured again */
716
- get: operations["capabilityRegistryFeed"];
715
+ /** MACHINE_CHAIN_HEAVY fix plan: the files read before the page and the absent-file 404s, measured reductions with the chain size after each, and the step at which the detector stops firing */
716
+ get: operations["fixMachineChain"];
717
717
  put?: never;
718
718
  post?: never;
719
719
  delete?: never;
@@ -722,15 +722,15 @@ export interface paths {
722
722
  patch?: never;
723
723
  trace?: never;
724
724
  };
725
- "/api/capabilities": {
725
+ "/api/fix/code": {
726
726
  parameters: {
727
727
  query?: never;
728
728
  header?: never;
729
729
  path?: never;
730
730
  cookie?: never;
731
731
  };
732
- /** Declared agent capabilities with safety class, verification state and declaration-vs-behaviour mismatches, from the latest scan */
733
- get: operations["listVerifiedCapabilities"];
732
+ /** PAGE_IS_MOSTLY_CODE fix plan: the measured byte breakdown, ordered steps with the ratio after each, the step at which the detector stops firing, or the markup/text change needed when moving code cannot clear it */
733
+ get: operations["fixMostlyCode"];
734
734
  put?: never;
735
735
  post?: never;
736
736
  delete?: never;
@@ -739,15 +739,15 @@ export interface paths {
739
739
  patch?: never;
740
740
  trace?: never;
741
741
  };
742
- "/api/v1/reports/{id}": {
742
+ "/api/corroboration": {
743
743
  parameters: {
744
744
  query?: never;
745
745
  header?: never;
746
746
  path?: never;
747
747
  cookie?: never;
748
748
  };
749
- /** A stored report as PublicReportV1 (licence or read-scoped API key) */
750
- get: operations["getReportV1"];
749
+ /** Each observer's reading of the identity-dependent findings side by side (primary Worker vs the independent second observer), with a corroboration status per finding */
750
+ get: operations["getCorroboration"];
751
751
  put?: never;
752
752
  post?: never;
753
753
  delete?: never;
@@ -756,15 +756,15 @@ export interface paths {
756
756
  patch?: never;
757
757
  trace?: never;
758
758
  };
759
- "/api/locate": {
759
+ "/api/explain": {
760
760
  parameters: {
761
761
  query?: never;
762
762
  header?: never;
763
763
  path?: never;
764
764
  cookie?: never;
765
765
  };
766
- /** Check every source locator in a record against the stored page: each extracted value's UTF-8 byte range is cut from the sealed page bytes (re-hashed first) and compared with the recorded value. With finding=CODE, the same for a finding: the robots.txt lines, the HTML tag served where a file should be, the empty <urlset>, an absence re-checked over the whole stored file, a manifest field */
767
- get: operations["locateFacts"];
766
+ /** One finding explained: rule and revision, compared fetches, valid time, Merkle proof of the decision in the signed manifest */
767
+ get: operations["explainFinding"];
768
768
  put?: never;
769
769
  post?: never;
770
770
  delete?: never;
@@ -773,49 +773,49 @@ export interface paths {
773
773
  patch?: never;
774
774
  trace?: never;
775
775
  };
776
- "/sdk/index.json": {
776
+ "/api/observe/enroll": {
777
777
  parameters: {
778
778
  query?: never;
779
779
  header?: never;
780
780
  path?: never;
781
781
  cookie?: never;
782
782
  };
783
- /** @crawlcheck/sdk versions: tarball URL, sha256, npm integrity string, the verifier it bundles and the number of API paths it is typed from. Install: npm i @crawlcheck/sdk (npm), or npm i https://crawlcheck.io/sdk/crawlcheck-sdk-<version>.tgz. Public */
784
- get: operations["sdkVersions"];
783
+ get?: never;
785
784
  put?: never;
786
- post?: never;
785
+ /** Enrol an independent observer (open observer protocol v1): an Ed25519 key, an id ind:<name>, operator and network, signed with the key it enrols; the id is bound to the first key that claims it */
786
+ post: operations["enrolObserver"];
787
787
  delete?: never;
788
788
  options?: never;
789
789
  head?: never;
790
790
  patch?: never;
791
791
  trace?: never;
792
792
  };
793
- "/conformance/index.json": {
793
+ "/api/observe/check": {
794
794
  parameters: {
795
795
  query?: never;
796
796
  header?: never;
797
797
  path?: never;
798
798
  cookie?: never;
799
799
  };
800
- /** The conformance suite: real bundles and receipts of crawlcheck.io's own scans (valid in three manifest eras, incomplete, unsealed, tampered one field at a time, contradictory, foreign-key) with the exact output a conforming verifier must give for every check, each file's SHA-256, and the runner (/conformance/run.mjs) that checks a verifier against all of them. Public */
801
- get: operations["conformanceIndex"];
800
+ get?: never;
802
801
  put?: never;
803
- post?: never;
802
+ /** Run the Worker's own checks on an observation or enrolment without storing it: shape, key against the directory entry (the live directory, or one you send), signature. The fixtures at /observer/fixtures.json run against it */
803
+ post: operations["checkObservation"];
804
804
  delete?: never;
805
805
  options?: never;
806
806
  head?: never;
807
807
  patch?: never;
808
808
  trace?: never;
809
809
  };
810
- "/api/receipt": {
810
+ "/api/data/inventory": {
811
811
  parameters: {
812
812
  query?: never;
813
813
  header?: never;
814
814
  path?: never;
815
815
  cookie?: never;
816
816
  };
817
- /** A signed remediation receipt by its id (rc1:<sha256>): the record before a fix, the declared fix, when it went live, the record after and the verification verdict with the files that changed, signed Ed25519 over sha256(canonical JSON). Returned with the server's own check; &download=1 gives the file for the offline verifier (node crawlcheck-verify.mjs receipt.json). The id is unguessable: whoever holds it can open it */
818
- get: operations["getReceipt"];
817
+ /** Everything held about a domain, signed: each family of stored keys with counts and bytes, what is kept after deletion and why. Licence for the domain or owner */
818
+ get: operations["dataInventory"];
819
819
  put?: never;
820
820
  post?: never;
821
821
  delete?: never;
@@ -824,49 +824,49 @@ export interface paths {
824
824
  patch?: never;
825
825
  trace?: never;
826
826
  };
827
- "/api/receipt/verify": {
827
+ "/api/data/export": {
828
828
  parameters: {
829
829
  query?: never;
830
830
  header?: never;
831
831
  path?: never;
832
832
  cookie?: never;
833
833
  };
834
- get?: never;
834
+ /** Export everything held about a domain in signed parts: part 0 = the inventory and every stored row; then archived records with the bytes each fetch received; then receipts, dispute resolutions and observations */
835
+ get: operations["dataExport"];
835
836
  put?: never;
836
- /** Verify any remediation receipt: POST its JSON; receipt_hash, key_id, key_published, signature. Public */
837
- post: operations["verifyReceipt"];
837
+ post?: never;
838
838
  delete?: never;
839
839
  options?: never;
840
840
  head?: never;
841
841
  patch?: never;
842
842
  trace?: never;
843
843
  };
844
- "/api/receipts": {
844
+ "/api/data/delete": {
845
845
  parameters: {
846
846
  query?: never;
847
847
  header?: never;
848
848
  path?: never;
849
849
  cookie?: never;
850
850
  };
851
- /** A site's receipts, newest first (licence or owner) */
852
- get: operations["listReceipts"];
851
+ get?: never;
853
852
  put?: never;
854
- post?: never;
853
+ /** Delete everything held about a domain: {domain, confirm: domain, inventory_sha256} starts a job (an inventory issued in the last 24 hours is required); POST {job} continues it. Ends in a signed deletion record */
854
+ post: operations["dataDelete"];
855
855
  delete?: never;
856
856
  options?: never;
857
857
  head?: never;
858
858
  patch?: never;
859
859
  trace?: never;
860
860
  };
861
- "/api/rules": {
861
+ "/api/data/deletion": {
862
862
  parameters: {
863
863
  query?: never;
864
864
  header?: never;
865
865
  path?: never;
866
866
  cookie?: never;
867
867
  };
868
- /** The rulebook: every finding code the scanner can raise, with what it means, its level, its fix and its share of counted scans. Public. ?code= returns one rule */
869
- get: operations["rulebook"];
868
+ /** A signed deletion record: counts per family and the digest of the deleted-key list, never the data */
869
+ get: operations["dataDeletionRecord"];
870
870
  put?: never;
871
871
  post?: never;
872
872
  delete?: never;
@@ -875,15 +875,15 @@ export interface paths {
875
875
  patch?: never;
876
876
  trace?: never;
877
877
  };
878
- "/schemas/rulebook.json": {
878
+ "/api/trace/coverage": {
879
879
  parameters: {
880
880
  query?: never;
881
881
  header?: never;
882
882
  path?: never;
883
883
  cookie?: never;
884
884
  };
885
- /** JSON Schema (2020-12) for /api/rules: RulebookV1 and RuleV1, the same definitions /api/v1/schema carries */
886
- get: operations["getRulebookSchema"];
885
+ /** Trace coverage: per scan, how many findings and claims link their own rule span, how many stage errors name a span, broken parent links, malformed or duplicate ids, dropped spans. ?id= one record (counts public; unlinked codes with a licence); without id the last 300 scans and the latest CI result */
886
+ get: operations["traceCoverage"];
887
887
  put?: never;
888
888
  post?: never;
889
889
  delete?: never;
@@ -892,100 +892,103 @@ export interface paths {
892
892
  patch?: never;
893
893
  trace?: never;
894
894
  };
895
- "/api/lineage-coverage": {
895
+ "/api/trace/ci": {
896
896
  parameters: {
897
897
  query?: never;
898
898
  header?: never;
899
899
  path?: never;
900
900
  cookie?: never;
901
901
  };
902
- /** The lineage coverage matrix: for every finding family, how many real findings carry each link of the evidence path (exact source locator, extraction, claim/observation, rule input, decision, score contribution, verified) and the replay of the rule over sealed bytes, computed from the newest stored records. Public, cached six hours */
903
- get: operations["lineageCoverage"];
902
+ /** The latest trace CI result (schema violations, broken parent links, unlinked findings) and its history */
903
+ get: operations["traceCiResult"];
904
904
  put?: never;
905
- post?: never;
905
+ /** Callable only by this repository's trace workflow (GitHub OIDC, audience crawlcheck-trace): phase sample returns real traces (TraceV1) to validate; phase report stores the verdict */
906
+ post: operations["traceCi"];
906
907
  delete?: never;
907
908
  options?: never;
908
909
  head?: never;
909
910
  patch?: never;
910
911
  trace?: never;
911
912
  };
912
- "/api/lineage": {
913
+ "/api/disputes": {
913
914
  parameters: {
914
915
  query?: never;
915
916
  header?: never;
916
917
  path?: never;
917
918
  cookie?: never;
918
919
  };
919
- /** One finding's evidence path, cell by cell, with the rule replayed over the sealed bytes where its input is sealed (and the reason where it is not). Gated like /api/explain: the top finding is free, a code lookup needs a licence for the domain */
920
- get: operations["findingLineage"];
920
+ /** The dispute and correction ledger: every dispute filed against a finding, its state and verdict. ?id=dsp1:… returns one dispute with its readings and events; ?domain= filters */
921
+ get: operations["disputeLedger"];
921
922
  put?: never;
922
- post?: never;
923
+ /** File a dispute against one finding on one record: {report_id, code, path?, ground: misread|fixed|network|rule, statement}. Accepted at once with a licence for the domain or the owner session; otherwise answers 202 with a token to serve at /.well-known/crawlcheck-dispute.txt */
924
+ post: operations["fileDispute"];
923
925
  delete?: never;
924
926
  options?: never;
925
927
  head?: never;
926
928
  patch?: never;
927
929
  trace?: never;
928
930
  };
929
- "/api/workflow": {
931
+ "/api/disputes/confirm": {
930
932
  parameters: {
931
933
  query?: never;
932
934
  header?: never;
933
935
  path?: never;
934
936
  cookie?: never;
935
937
  };
936
- /** One finding on one site, end to end: detected, exact evidence, fix recommended, impact projected, implementation recorded, rescanned, corroborated by a second observer, signed receipt, regression watch, outcomes. Every step is a link to the record that proves it, with done:true only when that record exists. Public for the exemplar sites on /workflow; a licence for the domain or the owner otherwise */
937
- get: operations["fixChain"];
938
+ get?: never;
938
939
  put?: never;
939
- post?: never;
940
+ /** After serving the token at https://<domain>/.well-known/crawlcheck-dispute.txt, accept the dispute */
941
+ post: operations["confirmDisputeOwnership"];
940
942
  delete?: never;
941
943
  options?: never;
942
944
  head?: never;
943
945
  patch?: never;
944
946
  trace?: never;
945
947
  };
946
- "/api/workflow/record": {
948
+ "/api/disputes/resolution": {
947
949
  parameters: {
948
950
  query?: never;
949
951
  header?: never;
950
952
  path?: never;
951
953
  cookie?: never;
952
954
  };
953
- get?: never;
955
+ /** A signed dispute resolution (machine record). Verify offline: node crawlcheck-verify.mjs resolution.json */
956
+ get: operations["getDisputeResolution"];
954
957
  put?: never;
955
- /** Record a fix: finds the newest record that carried the code and the first after it that did not, issues the signed remediation receipt with the declared fix inside it, and queues the second observer on the fixed URL (licence for the domain, or owner) */
956
- post: operations["recordFixChain"];
958
+ post?: never;
957
959
  delete?: never;
958
960
  options?: never;
959
961
  head?: never;
960
962
  patch?: never;
961
963
  trace?: never;
962
964
  };
963
- "/api/observation": {
965
+ "/api/disputes/verify": {
964
966
  parameters: {
965
967
  query?: never;
966
968
  header?: never;
967
969
  path?: never;
968
970
  cookie?: never;
969
971
  };
970
- /** One signed second-observer observation in full: the envelope (fetches with status, headers kept, sha256 of each body), the run key's Ed25519 signature, GitHub's OIDC token binding the key to the enrolled workflow, the checks run on receipt and the readings derived from the bytes. Public */
971
- get: operations["getObservation"];
972
+ /** Check a stored resolution server side: hash, key id, key published, signature, verdict re-derived, readings after the dispute */
973
+ get: operations["verifyDisputeResolution"];
972
974
  put?: never;
973
- post?: never;
975
+ /** Check a resolution you hold */
976
+ post: operations["verifyDisputeResolutionPost"];
974
977
  delete?: never;
975
978
  options?: never;
976
979
  head?: never;
977
980
  patch?: never;
978
981
  trace?: never;
979
982
  };
980
- "/api/outcomes": {
983
+ "/api/datasets": {
981
984
  parameters: {
982
985
  query?: never;
983
986
  header?: never;
984
987
  path?: never;
985
988
  cookie?: never;
986
989
  };
987
- /** What the owner's connected sources counted either side of a receipt's anchor day: Search Console clicks and impressions, Business Profile actions, verified crawler fetches from the site's own log, beacon arrivals, enquiries through the form and anything posted to /api/outcome. One named source per series, per-day means compared, a missing day never zero, a thin window reported as thin. A coincidence in time, stated as one: it never claims the fix caused the movement (licence for the domain, or owner) */
988
- get: operations["fixOutcomes"];
990
+ /** The dataset catalogue: counts per lane and day, the latest day's breakdown, the field dictionary and the technology list. Public */
991
+ get: operations["datasetCatalogue"];
989
992
  put?: never;
990
993
  post?: never;
991
994
  delete?: never;
@@ -994,15 +997,15 @@ export interface paths {
994
997
  patch?: never;
995
998
  trace?: never;
996
999
  };
997
- "/api/evidence/export": {
1000
+ "/api/datasets/sample": {
998
1001
  parameters: {
999
1002
  query?: never;
1000
1003
  header?: never;
1001
1004
  path?: never;
1002
1005
  cookie?: never;
1003
1006
  };
1004
- /** Evidence line: one signed file carrying every measurement (with its evidence bundle), receipt, certificate day and seal for a domain and period; verifies offline with crawlcheck-verify.mjs (Evidence add-on, Agency, or owner) */
1005
- get: operations["evidenceExport"];
1007
+ /** 25 measured rows from the latest files. Public */
1008
+ get: operations["datasetSample"];
1006
1009
  put?: never;
1007
1010
  post?: never;
1008
1011
  delete?: never;
@@ -1011,15 +1014,15 @@ export interface paths {
1011
1014
  patch?: never;
1012
1015
  trace?: never;
1013
1016
  };
1014
- "/api/evidence/ledger": {
1017
+ "/api/datasets/file": {
1015
1018
  parameters: {
1016
1019
  query?: never;
1017
1020
  header?: never;
1018
1021
  path?: never;
1019
1022
  cookie?: never;
1020
1023
  };
1021
- /** Evidence line: one row per measured day in the window with the day's reading, archived records and seal state, plus receipts and certificate history (Evidence add-on, Agency, or owner) */
1022
- get: operations["evidenceLedger"];
1024
+ /** One lane's file for one day, CSV or NDJSON, filterable. Needs a licence key with dataset access */
1025
+ get: operations["datasetFile"];
1023
1026
  put?: never;
1024
1027
  post?: never;
1025
1028
  delete?: never;
@@ -1028,15 +1031,15 @@ export interface paths {
1028
1031
  patch?: never;
1029
1032
  trace?: never;
1030
1033
  };
1031
- "/api/evidence/receipts": {
1034
+ "/api/datasets/state": {
1032
1035
  parameters: {
1033
1036
  query?: never;
1034
1037
  header?: never;
1035
1038
  path?: never;
1036
1039
  cookie?: never;
1037
1040
  };
1038
- /** Evidence line: every remediation receipt across every domain on the key, newest first (Evidence add-on, Agency, or owner) */
1039
- get: operations["evidenceReceipts"];
1041
+ /** One US state's local businesses across every day it was scanned. Needs a key with the local lane */
1042
+ get: operations["datasetState"];
1040
1043
  put?: never;
1041
1044
  post?: never;
1042
1045
  delete?: never;
@@ -1045,32 +1048,32 @@ export interface paths {
1045
1048
  patch?: never;
1046
1049
  trace?: never;
1047
1050
  };
1048
- "/api/benchmark": {
1051
+ "/api/datasets/request": {
1049
1052
  parameters: {
1050
1053
  query?: never;
1051
1054
  header?: never;
1052
1055
  path?: never;
1053
1056
  cookie?: never;
1054
1057
  };
1055
- /** Intelligence line: corpus percentile and next band, cohort metrics, and the rarity of each visible finding across daily-measured sites (Intelligence add-on, Growth, or owner) */
1056
- get: operations["benchmark"];
1058
+ get?: never;
1057
1059
  put?: never;
1058
- post?: never;
1060
+ /** Ask for dataset access. Public, one request a minute per address */
1061
+ post: operations["datasetRequest"];
1059
1062
  delete?: never;
1060
1063
  options?: never;
1061
1064
  head?: never;
1062
1065
  patch?: never;
1063
1066
  trace?: never;
1064
1067
  };
1065
- "/api/portfolio/compare": {
1068
+ "/api/lanes": {
1066
1069
  parameters: {
1067
1070
  query?: never;
1068
1071
  header?: never;
1069
1072
  path?: never;
1070
1073
  cookie?: never;
1071
1074
  };
1072
- /** Intelligence line: two to 40 domains side by side from their latest records, with the spread and the finding codes shared across them (Intelligence add-on, Growth, or owner) */
1073
- get: operations["portfolioCompare"];
1075
+ /** The day's scan lanes and their quotas (SaaS 5,000, government and education 2,500, one US state's local businesses 5,000): measured, unmeasured, kinds detected, the state in rotation. Public */
1076
+ get: operations["scanLanes"];
1074
1077
  put?: never;
1075
1078
  post?: never;
1076
1079
  delete?: never;
@@ -1079,32 +1082,32 @@ export interface paths {
1079
1082
  patch?: never;
1080
1083
  trace?: never;
1081
1084
  };
1082
- "/api/verify/bulk": {
1085
+ "/api/census": {
1083
1086
  parameters: {
1084
1087
  query?: never;
1085
1088
  header?: never;
1086
1089
  path?: never;
1087
1090
  cookie?: never;
1088
1091
  };
1089
- get?: never;
1092
+ /** The agentic-web census: the frame (a frozen Tranco top-1,000 list), every run, the latest figures with their denominators, and the change since the first run (percentage points and sites that gained or lost each property). Public */
1093
+ get: operations["agenticWebCensus"];
1090
1094
  put?: never;
1091
- /** Intelligence line: run every server-side verifier on up to 25 ids in one call (Intelligence add-on, Growth, or owner) */
1092
- post: operations["verifyBulk"];
1095
+ post?: never;
1093
1096
  delete?: never;
1094
1097
  options?: never;
1095
1098
  head?: never;
1096
1099
  patch?: never;
1097
1100
  trace?: never;
1098
1101
  };
1099
- "/api/rollback": {
1102
+ "/api/census/records": {
1100
1103
  parameters: {
1101
1104
  query?: never;
1102
1105
  header?: never;
1103
1106
  path?: never;
1104
1107
  cookie?: never;
1105
1108
  };
1106
- /** Compare the record before a fix with the record after it (licence or owner): findings cleared and new by fingerprint, rows now passing and now failing, every machine file whose bytes changed, a verdict (improved / unchanged / mixed / regressed), each regression pinned to the changed file it reads, and the rollback step for that file (restore the stored bytes, or remove a file that did not exist before) */
1107
- get: operations["verifyAndRollback"];
1109
+ /** One run's per-site records in frame order: the raw readings (statuses, sizes, SHA-256 of what each identity was served, the robots.txt text, each machine file) and the derived fields every figure counts */
1110
+ get: operations["censusRecords"];
1108
1111
  put?: never;
1109
1112
  post?: never;
1110
1113
  delete?: never;
@@ -1113,15 +1116,15 @@ export interface paths {
1113
1116
  patch?: never;
1114
1117
  trace?: never;
1115
1118
  };
1116
- "/api/rollback/file": {
1119
+ "/api/census/frame": {
1117
1120
  parameters: {
1118
1121
  query?: never;
1119
1122
  header?: never;
1120
1123
  path?: never;
1121
1124
  cookie?: never;
1122
1125
  };
1123
- /** The exact bytes a machine file served in a given record, from the artifact store, re-hashed before they are returned (licence or owner) */
1124
- get: operations["rollbackFile"];
1126
+ /** The census sampling frame: the Tranco list id and configuration, the members measured, and the counts excluded by the publish filter and by opt-out */
1127
+ get: operations["censusFrame"];
1125
1128
  put?: never;
1126
1129
  post?: never;
1127
1130
  delete?: never;
@@ -1130,51 +1133,50 @@ export interface paths {
1130
1133
  patch?: never;
1131
1134
  trace?: never;
1132
1135
  };
1133
- "/api/impact": {
1136
+ "/api/registry/capabilities": {
1134
1137
  parameters: {
1135
1138
  query?: never;
1136
1139
  header?: never;
1137
1140
  path?: never;
1138
1141
  cookie?: never;
1139
1142
  };
1140
- /** What fixing one thing changes on a record (licence or owner): per fix - robots, sitemap, llms, entitymap, edge-bots, cache, page-code, chain, hsts, host-pair - the findings and rows it clears, the ones it clears only together with another fix, the root causes it closes, the certificate criteria it flips and the score and letter after */
1141
- get: operations["fixImpact"];
1143
+ /** The capability registry: every measured site that declares agent capabilities, with counts by invocation policy class; ?domain= returns one site's capabilities declared beside observed, its mismatches and its signed capability certificate. Public */
1144
+ get: operations["capabilityRegistry"];
1142
1145
  put?: never;
1143
- /** The same with a body: {id, fix:[ids]} */
1144
- post: operations["fixImpactPost"];
1146
+ post?: never;
1145
1147
  delete?: never;
1146
1148
  options?: never;
1147
1149
  head?: never;
1148
1150
  patch?: never;
1149
1151
  trace?: never;
1150
1152
  };
1151
- "/api/whatif": {
1153
+ "/api/registry/capabilities/verify": {
1152
1154
  parameters: {
1153
1155
  query?: never;
1154
1156
  header?: never;
1155
1157
  path?: never;
1156
1158
  cookie?: never;
1157
1159
  };
1158
- /** Recompute the score and letter for a record with any set of failing rows passing and findings cleared (licence or owner): the combined effect, which individual points cannot give, plus the least set that reaches the next letter */
1159
- get: operations["whatIf"];
1160
+ /** Recompute a site's capability certificate from its stored record and verify it: hash, key id, published key, Ed25519 signature */
1161
+ get: operations["verifyCapabilityCertificate"];
1160
1162
  put?: never;
1161
- /** The same, with rows to fix: {id, fix:[{section_id,row}], clear:[codes]} */
1162
- post: operations["whatIfPost"];
1163
+ /** Verify a capability certificate you hold (the JSON from /api/registry/capabilities?domain=) */
1164
+ post: operations["verifyCapabilityCertificatePost"];
1163
1165
  delete?: never;
1164
1166
  options?: never;
1165
1167
  head?: never;
1166
1168
  patch?: never;
1167
1169
  trace?: never;
1168
1170
  };
1169
- "/ns": {
1171
+ "/registry/capabilities/feed.json": {
1170
1172
  parameters: {
1171
1173
  query?: never;
1172
1174
  header?: never;
1173
1175
  path?: never;
1174
1176
  cookie?: never;
1175
1177
  };
1176
- /** The CrawlCheck vocabulary (https://crawlcheck.io/ns#) as RDFS in JSON-LD: every class and property the JSON-LD export uses, with labels and comments */
1177
- get: operations["getVocabulary"];
1178
+ /** The capability registry as a JSON Feed 1.1: one item per site, updated when it is measured again */
1179
+ get: operations["capabilityRegistryFeed"];
1178
1180
  put?: never;
1179
1181
  post?: never;
1180
1182
  delete?: never;
@@ -1183,15 +1185,15 @@ export interface paths {
1183
1185
  patch?: never;
1184
1186
  trace?: never;
1185
1187
  };
1186
- "/schemas/openlineage-facets.json": {
1188
+ "/api/capabilities": {
1187
1189
  parameters: {
1188
1190
  query?: never;
1189
1191
  header?: never;
1190
1192
  path?: never;
1191
1193
  cookie?: never;
1192
1194
  };
1193
- /** JSON Schema for CrawlCheck's OpenLineage facets (CrawlCheckRunFacet, CrawlCheckFetchFacet, CrawlCheckReportFacet), each extending the OpenLineage 2-0-2 BaseFacet */
1194
- get: operations["getOpenLineageFacetSchema"];
1195
+ /** Declared agent capabilities with safety class, verification state and declaration-vs-behaviour mismatches, from the latest scan */
1196
+ get: operations["listVerifiedCapabilities"];
1195
1197
  put?: never;
1196
1198
  post?: never;
1197
1199
  delete?: never;
@@ -1200,15 +1202,15 @@ export interface paths {
1200
1202
  patch?: never;
1201
1203
  trace?: never;
1202
1204
  };
1203
- "/schemas/machine-experience-record.json": {
1205
+ "/api/v1/reports/{id}": {
1204
1206
  parameters: {
1205
1207
  query?: never;
1206
1208
  header?: never;
1207
1209
  path?: never;
1208
1210
  cookie?: never;
1209
1211
  };
1210
- /** JSON Schema (2020-12) for the sealed scan manifest: every fetch a scan made, as which identity, with which headers, what came back and whether the bytes were kept; validated against 221 sealed manifests */
1211
- get: operations["getMachineExperienceRecordSchema"];
1212
+ /** A stored report as PublicReportV1 (licence or read-scoped API key) */
1213
+ get: operations["getReportV1"];
1212
1214
  put?: never;
1213
1215
  post?: never;
1214
1216
  delete?: never;
@@ -1217,15 +1219,15 @@ export interface paths {
1217
1219
  patch?: never;
1218
1220
  trace?: never;
1219
1221
  };
1220
- "/api/v1/schema": {
1222
+ "/api/locate": {
1221
1223
  parameters: {
1222
1224
  query?: never;
1223
1225
  header?: never;
1224
1226
  path?: never;
1225
1227
  cookie?: never;
1226
1228
  };
1227
- /** JSON Schema for every v1 response */
1228
- get: operations["getSchemaV1"];
1229
+ /** Check every source locator in a record against the stored page: each extracted value's UTF-8 byte range is cut from the sealed page bytes (re-hashed first) and compared with the recorded value. With finding=CODE, the same for a finding: the robots.txt lines, the HTML tag served where a file should be, the empty <urlset>, an absence re-checked over the whole stored file, a manifest field */
1230
+ get: operations["locateFacts"];
1229
1231
  put?: never;
1230
1232
  post?: never;
1231
1233
  delete?: never;
@@ -1234,121 +1236,117 @@ export interface paths {
1234
1236
  patch?: never;
1235
1237
  trace?: never;
1236
1238
  };
1237
- "/api/keys": {
1239
+ "/sdk/index.json": {
1238
1240
  parameters: {
1239
1241
  query?: never;
1240
1242
  header?: never;
1241
1243
  path?: never;
1242
1244
  cookie?: never;
1243
1245
  };
1244
- /** List the scoped API keys on a licence (names, scopes, last use; never the keys) */
1245
- get: operations["listApiKeys"];
1246
+ /** @crawlcheck/sdk versions: tarball URL, sha256, npm integrity string, the verifier it bundles and the number of API paths it is typed from. Install: npm i @crawlcheck/sdk (npm), or npm i https://crawlcheck.io/sdk/crawlcheck-sdk-<version>.tgz. Public */
1247
+ get: operations["sdkVersions"];
1246
1248
  put?: never;
1247
- /** Create a scoped API key (shown once; stored as a SHA-256) */
1248
- post: operations["createApiKey"];
1249
- /** Revoke an API key by id */
1250
- delete: operations["revokeApiKey"];
1249
+ post?: never;
1250
+ delete?: never;
1251
1251
  options?: never;
1252
1252
  head?: never;
1253
1253
  patch?: never;
1254
1254
  trace?: never;
1255
1255
  };
1256
- "/api/share": {
1256
+ "/conformance/index.json": {
1257
1257
  parameters: {
1258
1258
  query?: never;
1259
1259
  header?: never;
1260
1260
  path?: never;
1261
1261
  cookie?: never;
1262
1262
  };
1263
- get?: never;
1263
+ /** The conformance suite: real bundles and receipts of crawlcheck.io's own scans (valid in three manifest eras, incomplete, unsealed, tampered one field at a time, contradictory, foreign-key) with the exact output a conforming verifier must give for every check, each file's SHA-256, and the runner (/conformance/run.mjs) that checks a verifier against all of them. Public */
1264
+ get: operations["conformanceIndex"];
1264
1265
  put?: never;
1265
- /** Create a scoped share link for one report (licence required; up to 90 days; revocable) */
1266
- post: operations["createShareLink"];
1267
- /** Revoke a share link created with the same licence */
1268
- delete: operations["revokeShareLink"];
1266
+ post?: never;
1267
+ delete?: never;
1269
1268
  options?: never;
1270
1269
  head?: never;
1271
1270
  patch?: never;
1272
1271
  trace?: never;
1273
1272
  };
1274
- "/api/scan/licensed": {
1273
+ "/api/receipt": {
1275
1274
  parameters: {
1276
1275
  query?: never;
1277
1276
  header?: never;
1278
1277
  path?: never;
1279
1278
  cookie?: never;
1280
1279
  };
1281
- get?: never;
1280
+ /** A signed remediation receipt by its id (rc1:<sha256>): the record before a fix, the declared fix, when it went live, the record after and the verification verdict with the files that changed, signed Ed25519 over sha256(canonical JSON). Returned with the server's own check; &download=1 gives the file for the offline verifier (node crawlcheck-verify.mjs receipt.json). The id is unguessable: whoever holds it can open it */
1281
+ get: operations["getReceipt"];
1282
1282
  put?: never;
1283
- /** Scan a domain on the licensed lane (valid licence key required; 60 scans per ten minutes per key; 404 without a key) */
1284
- post: operations["scanDomainLicensed"];
1283
+ post?: never;
1285
1284
  delete?: never;
1286
1285
  options?: never;
1287
1286
  head?: never;
1288
1287
  patch?: never;
1289
1288
  trace?: never;
1290
1289
  };
1291
- "/api/tool/wba": {
1290
+ "/api/receipt/verify": {
1292
1291
  parameters: {
1293
1292
  query?: never;
1294
1293
  header?: never;
1295
1294
  path?: never;
1296
1295
  cookie?: never;
1297
1296
  };
1298
- /** Audit a Web Bot Auth key directory: no redirects, content type, RFC 7638 thumbprints, and which keys the directory's own signatures prove */
1299
- get: operations["checkBotKeyDirectory"];
1297
+ get?: never;
1300
1298
  put?: never;
1301
- /** Verify a pasted Web Bot Auth request: the agent's directory, then the request's signature against a key the directory proves it holds */
1302
- post: operations["verifySignedBotRequest"];
1299
+ /** Verify any remediation receipt: POST its JSON; receipt_hash, key_id, key_published, signature. Public */
1300
+ post: operations["verifyReceipt"];
1303
1301
  delete?: never;
1304
1302
  options?: never;
1305
1303
  head?: never;
1306
1304
  patch?: never;
1307
1305
  trace?: never;
1308
1306
  };
1309
- "/api/tool/verify": {
1307
+ "/api/receipts": {
1310
1308
  parameters: {
1311
1309
  query?: never;
1312
1310
  header?: never;
1313
1311
  path?: never;
1314
1312
  cookie?: never;
1315
1313
  };
1316
- get?: never;
1314
+ /** A site's receipts, newest first (licence or owner) */
1315
+ get: operations["listReceipts"];
1317
1316
  put?: never;
1318
- /** Adjudicate crawler identity claims in raw access-log lines against each operator's published IP ranges */
1319
- post: operations["verifyCrawlerLog"];
1317
+ post?: never;
1320
1318
  delete?: never;
1321
1319
  options?: never;
1322
1320
  head?: never;
1323
1321
  patch?: never;
1324
1322
  trace?: never;
1325
1323
  };
1326
- "/api/depth": {
1324
+ "/api/rules": {
1327
1325
  parameters: {
1328
1326
  query?: never;
1329
1327
  header?: never;
1330
1328
  path?: never;
1331
1329
  cookie?: never;
1332
1330
  };
1333
- get?: never;
1331
+ /** The rulebook: every finding code the scanner can raise, with what it means, its level, its fix and its share of counted scans. Public. ?code= returns one rule */
1332
+ get: operations["rulebook"];
1334
1333
  put?: never;
1335
- /** Crawl the URLs the site declares and map the links between them: orphans, undeclared pages, per-page status, canonical, text ratio, JSON-LD, noindex. Up to 300 pages in one pass; pages up to 500 (Watch, Studio) or 5000 (Agency, Network) runs as a background job in chunks of 300, advanced by every poll of /api/depth/{id} and every hour. Sites declaring more than the cap are sampled across path families. Licence-gated; 404 without a key. Returns 202 with a job id */
1336
- post: operations["depthCrawl"];
1334
+ post?: never;
1337
1335
  delete?: never;
1338
1336
  options?: never;
1339
1337
  head?: never;
1340
1338
  patch?: never;
1341
1339
  trace?: never;
1342
1340
  };
1343
- "/api/depth/{id}": {
1341
+ "/schemas/rulebook.json": {
1344
1342
  parameters: {
1345
1343
  query?: never;
1346
1344
  header?: never;
1347
1345
  path?: never;
1348
1346
  cookie?: never;
1349
1347
  };
1350
- /** The depth-crawl record for a job id: orphans, undeclared, pages[], medians and stated limits */
1351
- get: operations["depthResult"];
1348
+ /** JSON Schema (2020-12) for /api/rules: RulebookV1 and RuleV1, the same definitions /api/v1/schema carries */
1349
+ get: operations["getRulebookSchema"];
1352
1350
  put?: never;
1353
1351
  post?: never;
1354
1352
  delete?: never;
@@ -1357,15 +1355,15 @@ export interface paths {
1357
1355
  patch?: never;
1358
1356
  trace?: never;
1359
1357
  };
1360
- "/api/usage": {
1358
+ "/api/lineage-coverage": {
1361
1359
  parameters: {
1362
1360
  query?: never;
1363
1361
  header?: never;
1364
1362
  path?: never;
1365
1363
  cookie?: never;
1366
1364
  };
1367
- /** This key's monthly scan quota and usage; every keyed response also carries x-crawlcheck-quota-* headers */
1368
- get: operations["usage"];
1365
+ /** The lineage coverage matrix: for every finding family, how many real findings carry each link of the evidence path (exact source locator, extraction, claim/observation, rule input, decision, score contribution, verified) and the replay of the rule over sealed bytes, computed from the newest stored records. Public, cached six hours */
1366
+ get: operations["lineageCoverage"];
1369
1367
  put?: never;
1370
1368
  post?: never;
1371
1369
  delete?: never;
@@ -1374,15 +1372,15 @@ export interface paths {
1374
1372
  patch?: never;
1375
1373
  trace?: never;
1376
1374
  };
1377
- "/api/verify": {
1375
+ "/api/lineage": {
1378
1376
  parameters: {
1379
1377
  query?: never;
1380
1378
  header?: never;
1381
1379
  path?: never;
1382
1380
  cookie?: never;
1383
1381
  };
1384
- /** Every verifier in one call: record digest, seal + Bitcoin anchor, manifest signature (WBA Ed25519), stored manifest bytes, kept artifacts, decision pointers, provenance envelope, self-audit. Public */
1385
- get: operations["verifyRecord"];
1382
+ /** One finding's evidence path, cell by cell, with the rule replayed over the sealed bytes where its input is sealed (and the reason where it is not). Gated like /api/explain: the top finding is free, a code lookup needs a licence for the domain */
1383
+ get: operations["findingLineage"];
1386
1384
  put?: never;
1387
1385
  post?: never;
1388
1386
  delete?: never;
@@ -1391,15 +1389,15 @@ export interface paths {
1391
1389
  patch?: never;
1392
1390
  trace?: never;
1393
1391
  };
1394
- "/api/bundle": {
1392
+ "/api/workflow": {
1395
1393
  parameters: {
1396
1394
  query?: never;
1397
1395
  header?: never;
1398
1396
  path?: never;
1399
1397
  cookie?: never;
1400
1398
  };
1401
- /** One evidence bundle that verifies offline: signed manifest + public key, record digest, Merkle path, the day's .ots bytes; the sealed subject with a licence covering the domain. Verify with /crawlcheck-verify.mjs. Public */
1402
- get: operations["evidenceBundle"];
1399
+ /** One finding on one site, end to end: detected, exact evidence, fix recommended, impact projected, implementation recorded, rescanned, corroborated by a second observer, signed receipt, regression watch, outcomes. Every step is a link to the record that proves it, with done:true only when that record exists. Public for the exemplar sites on /workflow; a licence for the domain or the owner otherwise */
1400
+ get: operations["fixChain"];
1403
1401
  put?: never;
1404
1402
  post?: never;
1405
1403
  delete?: never;
@@ -1408,7 +1406,7 @@ export interface paths {
1408
1406
  patch?: never;
1409
1407
  trace?: never;
1410
1408
  };
1411
- "/api/reconstruction/ci": {
1409
+ "/api/workflow/record": {
1412
1410
  parameters: {
1413
1411
  query?: never;
1414
1412
  header?: never;
@@ -1417,23 +1415,23 @@ export interface paths {
1417
1415
  };
1418
1416
  get?: never;
1419
1417
  put?: never;
1420
- /** The weekly reconstruction run, callable only by this repository's reconstruction workflow (GitHub OIDC token, audience crawlcheck-reconstruction). The 20 oldest archived reports resolved through the projections and from the permanent store alone, plus two finding-to-artifact traversals each; green only when every part is identical */
1421
- post: operations["reconstructionCi"];
1418
+ /** Record a fix: finds the newest record that carried the code and the first after it that did not, issues the signed remediation receipt with the declared fix inside it, and queues the second observer on the fixed URL (licence for the domain, or owner) */
1419
+ post: operations["recordFixChain"];
1422
1420
  delete?: never;
1423
1421
  options?: never;
1424
1422
  head?: never;
1425
1423
  patch?: never;
1426
1424
  trace?: never;
1427
1425
  };
1428
- "/api/reconstruction": {
1426
+ "/api/observation": {
1429
1427
  parameters: {
1430
1428
  query?: never;
1431
1429
  header?: never;
1432
1430
  path?: never;
1433
1431
  cookie?: never;
1434
1432
  };
1435
- /** The last reconstruction test: the oldest archived records' evidence paths (record, report node, decision nodes, manifest node, every verifier check) resolved through the 90-day projections and again from the permanent store alone (R2 archive + seal records), compared byte for byte after canonical serialisation. Public */
1436
- get: operations["reconstructionTest"];
1433
+ /** One signed second-observer observation in full: the envelope (fetches with status, headers kept, sha256 of each body), the run key's Ed25519 signature, GitHub's OIDC token binding the key to the enrolled workflow, the checks run on receipt and the readings derived from the bytes. Public */
1434
+ get: operations["getObservation"];
1437
1435
  put?: never;
1438
1436
  post?: never;
1439
1437
  delete?: never;
@@ -1442,15 +1440,15 @@ export interface paths {
1442
1440
  patch?: never;
1443
1441
  trace?: never;
1444
1442
  };
1445
- "/api/graph/{id}": {
1443
+ "/api/outcomes": {
1446
1444
  parameters: {
1447
1445
  query?: never;
1448
1446
  header?: never;
1449
1447
  path?: never;
1450
1448
  cookie?: never;
1451
1449
  };
1452
- /** Resolve a finding id (f1:), decision id (d1:), manifest/artifact sha256 or report id to its graph object: evidence, rule, provenance, supporting experiences, seal, onward links. Licence-gated */
1453
- get: operations["graphResolve"];
1450
+ /** What the owner's connected sources counted either side of a receipt's anchor day: Search Console clicks and impressions, Business Profile actions, verified crawler fetches from the site's own log, beacon arrivals, enquiries through the form and anything posted to /api/outcome. One named source per series, per-day means compared, a missing day never zero, a thin window reported as thin. A coincidence in time, stated as one: it never claims the fix caused the movement (licence for the domain, or owner) */
1451
+ get: operations["fixOutcomes"];
1454
1452
  put?: never;
1455
1453
  post?: never;
1456
1454
  delete?: never;
@@ -1459,32 +1457,32 @@ export interface paths {
1459
1457
  patch?: never;
1460
1458
  trace?: never;
1461
1459
  };
1462
- "/api/batch": {
1460
+ "/api/evidence/export": {
1463
1461
  parameters: {
1464
1462
  query?: never;
1465
1463
  header?: never;
1466
1464
  path?: never;
1467
1465
  cookie?: never;
1468
1466
  };
1469
- get?: never;
1467
+ /** Evidence line: one signed file carrying every measurement (with its evidence bundle), receipt, certificate day and seal for a domain and period; verifies offline with crawlcheck-verify.mjs (Evidence add-on, Agency, or owner) */
1468
+ get: operations["evidenceExport"];
1470
1469
  put?: never;
1471
- /** Queue up to 100 domains (500 on Agency/Network) for the same audit /api/v1/scan runs; worked at minutes 17 past each hour UTC; optional signed https webhook on completion */
1472
- post: operations["batchSubmit"];
1470
+ post?: never;
1473
1471
  delete?: never;
1474
1472
  options?: never;
1475
1473
  head?: never;
1476
1474
  patch?: never;
1477
1475
  trace?: never;
1478
1476
  };
1479
- "/api/batch/{id}": {
1477
+ "/api/evidence/ledger": {
1480
1478
  parameters: {
1481
1479
  query?: never;
1482
1480
  header?: never;
1483
1481
  path?: never;
1484
1482
  cookie?: never;
1485
1483
  };
1486
- /** Batch state and per-domain results (grade, overall, refused, report links) */
1487
- get: operations["batchStatus"];
1484
+ /** Evidence line: one row per measured day in the window with the day's reading, archived records and seal state, plus receipts and certificate history (Evidence add-on, Agency, or owner) */
1485
+ get: operations["evidenceLedger"];
1488
1486
  put?: never;
1489
1487
  post?: never;
1490
1488
  delete?: never;
@@ -1493,15 +1491,15 @@ export interface paths {
1493
1491
  patch?: never;
1494
1492
  trace?: never;
1495
1493
  };
1496
- "/api/flow": {
1494
+ "/api/evidence/receipts": {
1497
1495
  parameters: {
1498
1496
  query?: never;
1499
1497
  header?: never;
1500
1498
  path?: never;
1501
1499
  cookie?: never;
1502
1500
  };
1503
- /** The observed data flow for a domain: where each crawler identity's path dies (edge, robots.txt as a file, robots.txt rules) and which stores it reached. Uses the latest record on file, or scans first when there is none (fresh=1). Answer-engine output is drawn, never measured */
1504
- get: operations["crawlerFlow"];
1501
+ /** Evidence line: every remediation receipt across every domain on the key, newest first (Evidence add-on, Agency, or owner) */
1502
+ get: operations["evidenceReceipts"];
1505
1503
  put?: never;
1506
1504
  post?: never;
1507
1505
  delete?: never;
@@ -1510,15 +1508,15 @@ export interface paths {
1510
1508
  patch?: never;
1511
1509
  trace?: never;
1512
1510
  };
1513
- "/api/flow/gate": {
1511
+ "/api/benchmark": {
1514
1512
  parameters: {
1515
1513
  query?: never;
1516
1514
  header?: never;
1517
1515
  path?: never;
1518
1516
  cookie?: never;
1519
1517
  };
1520
- /** CI gate for a domain the key covers: 200 pass, 412 fail when a crawler path open at the last sealed scan closed, a file broke, or a declared path is violated at critical/high */
1521
- get: operations["flowGate"];
1518
+ /** Intelligence line: corpus percentile and next band, cohort metrics, and the rarity of each visible finding across daily-measured sites (Intelligence add-on, Growth, or owner) */
1519
+ get: operations["benchmark"];
1522
1520
  put?: never;
1523
1521
  post?: never;
1524
1522
  delete?: never;
@@ -1527,51 +1525,49 @@ export interface paths {
1527
1525
  patch?: never;
1528
1526
  trace?: never;
1529
1527
  };
1530
- "/api/flow/declared": {
1528
+ "/api/portfolio/compare": {
1531
1529
  parameters: {
1532
1530
  query?: never;
1533
1531
  header?: never;
1534
1532
  path?: never;
1535
1533
  cookie?: never;
1536
1534
  };
1537
- /** The owner's declared flow for a domain the key covers, with parity against the latest scan */
1538
- get: operations["flowDeclaredGet"];
1539
- /** Set the declared flow: agents {id: reach|blocked|any}, stores {id: present|absent|any}, or {seed: observed} to start from the latest scan */
1540
- put: operations["flowDeclaredPut"];
1535
+ /** Intelligence line: two to 40 domains side by side from their latest records, with the spread and the finding codes shared across them (Intelligence add-on, Growth, or owner) */
1536
+ get: operations["portfolioCompare"];
1537
+ put?: never;
1541
1538
  post?: never;
1542
- /** Remove the declared flow */
1543
- delete: operations["flowDeclaredDelete"];
1539
+ delete?: never;
1544
1540
  options?: never;
1545
1541
  head?: never;
1546
1542
  patch?: never;
1547
1543
  trace?: never;
1548
1544
  };
1549
- "/api/tool/robots": {
1545
+ "/api/verify/bulk": {
1550
1546
  parameters: {
1551
1547
  query?: never;
1552
1548
  header?: never;
1553
1549
  path?: never;
1554
1550
  cookie?: never;
1555
1551
  };
1556
- /** Resolve every named answer engine, search index and training crawler against a domain's robots.txt the way a crawler does: most-specific group only, longest match, allow wins a tie */
1557
- get: operations["robotsResolve"];
1552
+ get?: never;
1558
1553
  put?: never;
1559
- post?: never;
1554
+ /** Intelligence line: run every server-side verifier on up to 25 ids in one call (Intelligence add-on, Growth, or owner) */
1555
+ post: operations["verifyBulk"];
1560
1556
  delete?: never;
1561
1557
  options?: never;
1562
1558
  head?: never;
1563
1559
  patch?: never;
1564
1560
  trace?: never;
1565
1561
  };
1566
- "/api/tool/llms": {
1562
+ "/api/rollback": {
1567
1563
  parameters: {
1568
1564
  query?: never;
1569
1565
  header?: never;
1570
1566
  path?: never;
1571
1567
  cookie?: never;
1572
1568
  };
1573
- /** Draft an llms.txt from the domain's own homepage and up to 25 declared pages, using their titles and descriptions. A draft, not a publication */
1574
- get: operations["llmsDraft"];
1569
+ /** Compare the record before a fix with the record after it (licence or owner): findings cleared and new by fingerprint, rows now passing and now failing, every machine file whose bytes changed, a verdict (improved / unchanged / mixed / regressed), each regression pinned to the changed file it reads, and the rollback step for that file (restore the stored bytes, or remove a file that did not exist before) */
1570
+ get: operations["verifyAndRollback"];
1575
1571
  put?: never;
1576
1572
  post?: never;
1577
1573
  delete?: never;
@@ -1580,15 +1576,15 @@ export interface paths {
1580
1576
  patch?: never;
1581
1577
  trace?: never;
1582
1578
  };
1583
- "/api/video": {
1579
+ "/api/rollback/file": {
1584
1580
  parameters: {
1585
1581
  query?: never;
1586
1582
  header?: never;
1587
1583
  path?: never;
1588
1584
  cookie?: never;
1589
1585
  };
1590
- /** One YouTube video against the video anchor model: twelve checks, each naming what it reads. Cached six hours */
1591
- get: operations["videoCheck"];
1586
+ /** The exact bytes a machine file served in a given record, from the artifact store, re-hashed before they are returned (licence or owner) */
1587
+ get: operations["rollbackFile"];
1592
1588
  put?: never;
1593
1589
  post?: never;
1594
1590
  delete?: never;
@@ -1597,15 +1593,51 @@ export interface paths {
1597
1593
  patch?: never;
1598
1594
  trace?: never;
1599
1595
  };
1600
- "/api/video/channel": {
1596
+ "/api/impact": {
1601
1597
  parameters: {
1602
1598
  query?: never;
1603
1599
  header?: never;
1604
1600
  path?: never;
1605
1601
  cookie?: never;
1606
1602
  };
1607
- /** Every upload on a channel, read 50 at a time. The upload list is free; the per-check tally (checks=1) is for Watch licences and above */
1608
- get: operations["videoChannel"];
1603
+ /** What fixing one thing changes on a record (licence or owner): per fix - robots, sitemap, llms, entitymap, edge-bots, cache, page-code, chain, hsts, host-pair - the findings and rows it clears, the ones it clears only together with another fix, the root causes it closes, the certificate criteria it flips and the score and letter after */
1604
+ get: operations["fixImpact"];
1605
+ put?: never;
1606
+ /** The same with a body: {id, fix:[ids]} */
1607
+ post: operations["fixImpactPost"];
1608
+ delete?: never;
1609
+ options?: never;
1610
+ head?: never;
1611
+ patch?: never;
1612
+ trace?: never;
1613
+ };
1614
+ "/api/whatif": {
1615
+ parameters: {
1616
+ query?: never;
1617
+ header?: never;
1618
+ path?: never;
1619
+ cookie?: never;
1620
+ };
1621
+ /** Recompute the score and letter for a record with any set of failing rows passing and findings cleared (licence or owner): the combined effect, which individual points cannot give, plus the least set that reaches the next letter */
1622
+ get: operations["whatIf"];
1623
+ put?: never;
1624
+ /** The same, with rows to fix: {id, fix:[{section_id,row}], clear:[codes]} */
1625
+ post: operations["whatIfPost"];
1626
+ delete?: never;
1627
+ options?: never;
1628
+ head?: never;
1629
+ patch?: never;
1630
+ trace?: never;
1631
+ };
1632
+ "/ns": {
1633
+ parameters: {
1634
+ query?: never;
1635
+ header?: never;
1636
+ path?: never;
1637
+ cookie?: never;
1638
+ };
1639
+ /** The CrawlCheck vocabulary (https://crawlcheck.io/ns#) as RDFS in JSON-LD: every class and property the JSON-LD export uses, with labels and comments */
1640
+ get: operations["getVocabulary"];
1609
1641
  put?: never;
1610
1642
  post?: never;
1611
1643
  delete?: never;
@@ -1614,15 +1646,15 @@ export interface paths {
1614
1646
  patch?: never;
1615
1647
  trace?: never;
1616
1648
  };
1617
- "/api/video/site": {
1649
+ "/schemas/openlineage-facets.json": {
1618
1650
  parameters: {
1619
1651
  query?: never;
1620
1652
  header?: never;
1621
1653
  path?: never;
1622
1654
  cookie?: never;
1623
1655
  };
1624
- /** The site half: homepage plus up to 60 sitemap pages read for YouTube embeds, facades and page-builder widgets, VideoObject nodes and their required properties, and - with a handle - how many of the channel's videos the site carries */
1625
- get: operations["videoSite"];
1656
+ /** JSON Schema for CrawlCheck's OpenLineage facets (CrawlCheckRunFacet, CrawlCheckFetchFacet, CrawlCheckReportFacet), each extending the OpenLineage 2-0-2 BaseFacet */
1657
+ get: operations["getOpenLineageFacetSchema"];
1626
1658
  put?: never;
1627
1659
  post?: never;
1628
1660
  delete?: never;
@@ -1631,15 +1663,15 @@ export interface paths {
1631
1663
  patch?: never;
1632
1664
  trace?: never;
1633
1665
  };
1634
- "/api/fix/robots": {
1666
+ "/schemas/machine-experience-record.json": {
1635
1667
  parameters: {
1636
1668
  query?: never;
1637
1669
  header?: never;
1638
1670
  path?: never;
1639
1671
  cookie?: never;
1640
1672
  };
1641
- /** The served robots.txt, corrected: * group rules copied into every named group that lacked them, a Sitemap line added when the file never named the sitemap it serves, a minimal replacement when the served file was HTML. Every change is listed at the top of the file */
1642
- get: operations["fixRobots"];
1673
+ /** JSON Schema (2020-12) for the sealed scan manifest: every fetch a scan made, as which identity, with which headers, what came back and whether the bytes were kept; validated against 221 sealed manifests */
1674
+ get: operations["getMachineExperienceRecordSchema"];
1643
1675
  put?: never;
1644
1676
  post?: never;
1645
1677
  delete?: never;
@@ -1648,15 +1680,15 @@ export interface paths {
1648
1680
  patch?: never;
1649
1681
  trace?: never;
1650
1682
  };
1651
- "/api/fix/entitymap": {
1683
+ "/api/v1/schema": {
1652
1684
  parameters: {
1653
1685
  query?: never;
1654
1686
  header?: never;
1655
1687
  path?: never;
1656
1688
  cookie?: never;
1657
1689
  };
1658
- /** A starter entitymap.json built from the latest scan record: name, phone, coordinates and every declared service area as entities with SERVES relations. Fields the page never stated are marked TODO, never guessed. Needs a prior scan */
1659
- get: operations["fixEntitymap"];
1690
+ /** JSON Schema for every v1 response */
1691
+ get: operations["getSchemaV1"];
1660
1692
  put?: never;
1661
1693
  post?: never;
1662
1694
  delete?: never;
@@ -1665,7 +1697,26 @@ export interface paths {
1665
1697
  patch?: never;
1666
1698
  trace?: never;
1667
1699
  };
1668
- "/api/entity/observe": {
1700
+ "/api/keys": {
1701
+ parameters: {
1702
+ query?: never;
1703
+ header?: never;
1704
+ path?: never;
1705
+ cookie?: never;
1706
+ };
1707
+ /** List the scoped API keys on a licence (names, scopes, last use; never the keys) */
1708
+ get: operations["listApiKeys"];
1709
+ put?: never;
1710
+ /** Create a scoped API key (shown once; stored as a SHA-256) */
1711
+ post: operations["createApiKey"];
1712
+ /** Revoke an API key by id */
1713
+ delete: operations["revokeApiKey"];
1714
+ options?: never;
1715
+ head?: never;
1716
+ patch?: never;
1717
+ trace?: never;
1718
+ };
1719
+ "/api/share": {
1669
1720
  parameters: {
1670
1721
  query?: never;
1671
1722
  header?: never;
@@ -1674,23 +1725,93 @@ export interface paths {
1674
1725
  };
1675
1726
  get?: never;
1676
1727
  put?: never;
1677
- /** File a profile page as the owner's browser saw it, for the entity corroboration section. Consulted only where the scanner's own fetch was unverifiable; never overrides a live result; the row is labelled owner-browser. Licence-gated and bound to the licence's domains; the page's canonical must name the url's host. Kept 30 days */
1678
- post: operations["entityObserve"];
1728
+ /** Create a scoped share link for one report (licence required; up to 90 days; revocable) */
1729
+ post: operations["createShareLink"];
1730
+ /** Revoke a share link created with the same licence */
1731
+ delete: operations["revokeShareLink"];
1732
+ options?: never;
1733
+ head?: never;
1734
+ patch?: never;
1735
+ trace?: never;
1736
+ };
1737
+ "/api/scan/licensed": {
1738
+ parameters: {
1739
+ query?: never;
1740
+ header?: never;
1741
+ path?: never;
1742
+ cookie?: never;
1743
+ };
1744
+ get?: never;
1745
+ put?: never;
1746
+ /** Scan a domain on the licensed lane (valid licence key required; 60 scans per ten minutes per key; 404 without a key) */
1747
+ post: operations["scanDomainLicensed"];
1679
1748
  delete?: never;
1680
1749
  options?: never;
1681
1750
  head?: never;
1682
1751
  patch?: never;
1683
1752
  trace?: never;
1684
1753
  };
1685
- "/api/public/counts": {
1754
+ "/api/tool/wba": {
1686
1755
  parameters: {
1687
1756
  query?: never;
1688
1757
  header?: never;
1689
1758
  path?: never;
1690
1759
  cookie?: never;
1691
1760
  };
1692
- /** The figures this site quotes about itself: sites_measured, domains_in_corpus (two different quantities), crawler_visits (a rolling window), queue, identities_sent, sections, sections_scored (derived from the weights map), findings_published, guides_published and an at timestamp. CORS open, cached 60 seconds */
1693
- get: operations["publicCounts"];
1761
+ /** Audit a Web Bot Auth key directory: no redirects, content type, RFC 7638 thumbprints, and which keys the directory's own signatures prove */
1762
+ get: operations["checkBotKeyDirectory"];
1763
+ put?: never;
1764
+ /** Verify a pasted Web Bot Auth request: the agent's directory, then the request's signature against a key the directory proves it holds */
1765
+ post: operations["verifySignedBotRequest"];
1766
+ delete?: never;
1767
+ options?: never;
1768
+ head?: never;
1769
+ patch?: never;
1770
+ trace?: never;
1771
+ };
1772
+ "/api/tool/verify": {
1773
+ parameters: {
1774
+ query?: never;
1775
+ header?: never;
1776
+ path?: never;
1777
+ cookie?: never;
1778
+ };
1779
+ get?: never;
1780
+ put?: never;
1781
+ /** Adjudicate crawler identity claims in raw access-log lines against each operator's published IP ranges */
1782
+ post: operations["verifyCrawlerLog"];
1783
+ delete?: never;
1784
+ options?: never;
1785
+ head?: never;
1786
+ patch?: never;
1787
+ trace?: never;
1788
+ };
1789
+ "/api/depth": {
1790
+ parameters: {
1791
+ query?: never;
1792
+ header?: never;
1793
+ path?: never;
1794
+ cookie?: never;
1795
+ };
1796
+ get?: never;
1797
+ put?: never;
1798
+ /** Crawl the URLs the site declares and map the links between them: orphans, undeclared pages, per-page status, canonical, text ratio, JSON-LD, noindex. Up to 300 pages in one pass; pages up to 500 (Watch, Studio) or 5000 (Agency, Network) runs as a background job in chunks of 300, advanced by every poll of /api/depth/{id} and every hour. Sites declaring more than the cap are sampled across path families. Licence-gated; 404 without a key. Returns 202 with a job id */
1799
+ post: operations["depthCrawl"];
1800
+ delete?: never;
1801
+ options?: never;
1802
+ head?: never;
1803
+ patch?: never;
1804
+ trace?: never;
1805
+ };
1806
+ "/api/depth/{id}": {
1807
+ parameters: {
1808
+ query?: never;
1809
+ header?: never;
1810
+ path?: never;
1811
+ cookie?: never;
1812
+ };
1813
+ /** The depth-crawl record for a job id: orphans, undeclared, pages[], medians and stated limits */
1814
+ get: operations["depthResult"];
1694
1815
  put?: never;
1695
1816
  post?: never;
1696
1817
  delete?: never;
@@ -1699,15 +1820,15 @@ export interface paths {
1699
1820
  patch?: never;
1700
1821
  trace?: never;
1701
1822
  };
1702
- "/api/registry": {
1823
+ "/api/usage": {
1703
1824
  parameters: {
1704
1825
  query?: never;
1705
1826
  header?: never;
1706
1827
  path?: never;
1707
1828
  cookie?: never;
1708
1829
  };
1709
- /** The registry: which measured domains serve an llms.txt, an agents.md, a media kit, a reciprocity-tested entity graph, an AI access policy that names crawlers, or agent-callable surfaces */
1710
- get: operations["registry"];
1830
+ /** This key's monthly scan quota and usage; every keyed response also carries x-crawlcheck-quota-* headers */
1831
+ get: operations["usage"];
1711
1832
  put?: never;
1712
1833
  post?: never;
1713
1834
  delete?: never;
@@ -1716,15 +1837,15 @@ export interface paths {
1716
1837
  patch?: never;
1717
1838
  trace?: never;
1718
1839
  };
1719
- "/api/telemetry": {
1840
+ "/api/verify": {
1720
1841
  parameters: {
1721
1842
  query?: never;
1722
1843
  header?: never;
1723
1844
  path?: never;
1724
1845
  cookie?: never;
1725
1846
  };
1726
- /** Verified-crawler telemetry observed at this origin */
1727
- get: operations["telemetry"];
1847
+ /** Every verifier in one call: record digest, seal + Bitcoin anchor, manifest signature (WBA Ed25519), stored manifest bytes, kept artifacts, decision pointers, provenance envelope, self-audit. Public */
1848
+ get: operations["verifyRecord"];
1728
1849
  put?: never;
1729
1850
  post?: never;
1730
1851
  delete?: never;
@@ -1733,15 +1854,15 @@ export interface paths {
1733
1854
  patch?: never;
1734
1855
  trace?: never;
1735
1856
  };
1736
- "/api/corpus/state": {
1857
+ "/api/bundle": {
1737
1858
  parameters: {
1738
1859
  query?: never;
1739
1860
  header?: never;
1740
1861
  path?: never;
1741
1862
  cookie?: never;
1742
1863
  };
1743
- /** Coverage of the public dataset by platform, rendering, size, language and kind */
1744
- get: operations["corpusState"];
1864
+ /** One evidence bundle that verifies offline: signed manifest + public key, record digest, Merkle path, the day's .ots bytes; the sealed subject with a licence covering the domain. Verify with /crawlcheck-verify.mjs. Public */
1865
+ get: operations["evidenceBundle"];
1745
1866
  put?: never;
1746
1867
  post?: never;
1747
1868
  delete?: never;
@@ -1750,724 +1871,1780 @@ export interface paths {
1750
1871
  patch?: never;
1751
1872
  trace?: never;
1752
1873
  };
1753
- }
1754
- export type webhooks = Record<string, never>;
1755
- export interface components {
1756
- schemas: {
1757
- ScanRecord: {
1758
- /** @description Report id; the report renders at /r/{id} and the record at /r/{id}.json */
1759
- id?: string;
1760
- domain?: string;
1761
- /**
1762
- * @description null when the origin refused the scanner or the scan could not be graded
1763
- * @enum {string|null}
1764
- */
1765
- grade?: "A" | "B" | "C" | "D" | "F" | null;
1766
- /** @description AI visibility: reach, then read, then quote */
1767
- overall?: number | null;
1768
- /** @description The homepage and a path that cannot exist answered identically: a wall, not a site. Nothing is scored */
1769
- refused?: boolean;
1770
- section_scores?: {
1771
- id?: string;
1772
- title?: string;
1773
- score?: number | null;
1774
- }[];
1775
- findings?: {
1776
- code?: string;
1777
- severity?: number;
1778
- path?: string;
1779
- title?: string;
1780
- detail?: string;
1781
- evidence?: unknown;
1782
- }[];
1783
- /** @description Invariants checked on this record itself; a finding here is a defect in the scanner, never in the site */
1784
- self_audit?: Record<string, never>;
1874
+ "/api/reconstruction/ci": {
1875
+ parameters: {
1876
+ query?: never;
1877
+ header?: never;
1878
+ path?: never;
1879
+ cookie?: never;
1785
1880
  };
1786
- VerifyResult: {
1787
- tally?: {
1788
- verified?: number;
1789
- spoofed?: number;
1790
- unverifiable?: number;
1791
- no_bot?: number;
1792
- };
1793
- forged_rate_pct?: number | null;
1794
- denominator_note?: string;
1795
- rows?: Record<string, never>[];
1881
+ get?: never;
1882
+ put?: never;
1883
+ /** The weekly reconstruction run, callable only by this repository's reconstruction workflow (GitHub OIDC token, audience crawlcheck-reconstruction). The 20 oldest archived reports resolved through the projections and from the permanent store alone, plus two finding-to-artifact traversals each; green only when every part is identical */
1884
+ post: operations["reconstructionCi"];
1885
+ delete?: never;
1886
+ options?: never;
1887
+ head?: never;
1888
+ patch?: never;
1889
+ trace?: never;
1890
+ };
1891
+ "/api/reconstruction": {
1892
+ parameters: {
1893
+ query?: never;
1894
+ header?: never;
1895
+ path?: never;
1896
+ cookie?: never;
1897
+ };
1898
+ /** The last reconstruction test: the oldest archived records' evidence paths (record, report node, decision nodes, manifest node, every verifier check) resolved through the 90-day projections and again from the permanent store alone (R2 archive + seal records), compared byte for byte after canonical serialisation. Public */
1899
+ get: operations["reconstructionTest"];
1900
+ put?: never;
1901
+ post?: never;
1902
+ delete?: never;
1903
+ options?: never;
1904
+ head?: never;
1905
+ patch?: never;
1906
+ trace?: never;
1907
+ };
1908
+ "/api/graph/{id}": {
1909
+ parameters: {
1910
+ query?: never;
1911
+ header?: never;
1912
+ path?: never;
1913
+ cookie?: never;
1914
+ };
1915
+ /** Resolve a finding id (f1:), decision id (d1:), manifest/artifact sha256 or report id to its graph object: evidence, rule, provenance, supporting experiences, seal, onward links. Licence-gated */
1916
+ get: operations["graphResolve"];
1917
+ put?: never;
1918
+ post?: never;
1919
+ delete?: never;
1920
+ options?: never;
1921
+ head?: never;
1922
+ patch?: never;
1923
+ trace?: never;
1924
+ };
1925
+ "/api/batch": {
1926
+ parameters: {
1927
+ query?: never;
1928
+ header?: never;
1929
+ path?: never;
1930
+ cookie?: never;
1931
+ };
1932
+ get?: never;
1933
+ put?: never;
1934
+ /** Queue up to 100 domains (500 on Agency/Network) for the same audit /api/v1/scan runs; worked at minutes 17 past each hour UTC; optional signed https webhook on completion */
1935
+ post: operations["batchSubmit"];
1936
+ delete?: never;
1937
+ options?: never;
1938
+ head?: never;
1939
+ patch?: never;
1940
+ trace?: never;
1941
+ };
1942
+ "/api/batch/{id}": {
1943
+ parameters: {
1944
+ query?: never;
1945
+ header?: never;
1946
+ path?: never;
1947
+ cookie?: never;
1948
+ };
1949
+ /** Batch state and per-domain results (grade, overall, refused, report links) */
1950
+ get: operations["batchStatus"];
1951
+ put?: never;
1952
+ post?: never;
1953
+ delete?: never;
1954
+ options?: never;
1955
+ head?: never;
1956
+ patch?: never;
1957
+ trace?: never;
1958
+ };
1959
+ "/api/flow": {
1960
+ parameters: {
1961
+ query?: never;
1962
+ header?: never;
1963
+ path?: never;
1964
+ cookie?: never;
1965
+ };
1966
+ /** The observed data flow for a domain: where each crawler identity's path dies (edge, robots.txt as a file, robots.txt rules) and which stores it reached. Uses the latest record on file, or scans first when there is none (fresh=1). Answer-engine output is drawn, never measured */
1967
+ get: operations["crawlerFlow"];
1968
+ put?: never;
1969
+ post?: never;
1970
+ delete?: never;
1971
+ options?: never;
1972
+ head?: never;
1973
+ patch?: never;
1974
+ trace?: never;
1975
+ };
1976
+ "/api/flow/gate": {
1977
+ parameters: {
1978
+ query?: never;
1979
+ header?: never;
1980
+ path?: never;
1981
+ cookie?: never;
1982
+ };
1983
+ /** CI gate for a domain the key covers: 200 pass, 412 fail when a crawler path open at the last sealed scan closed, a file broke, or a declared path is violated at critical/high */
1984
+ get: operations["flowGate"];
1985
+ put?: never;
1986
+ post?: never;
1987
+ delete?: never;
1988
+ options?: never;
1989
+ head?: never;
1990
+ patch?: never;
1991
+ trace?: never;
1992
+ };
1993
+ "/api/flow/declared": {
1994
+ parameters: {
1995
+ query?: never;
1996
+ header?: never;
1997
+ path?: never;
1998
+ cookie?: never;
1999
+ };
2000
+ /** The owner's declared flow for a domain the key covers, with parity against the latest scan */
2001
+ get: operations["flowDeclaredGet"];
2002
+ /** Set the declared flow: agents {id: reach|blocked|any}, stores {id: present|absent|any}, or {seed: observed} to start from the latest scan */
2003
+ put: operations["flowDeclaredPut"];
2004
+ post?: never;
2005
+ /** Remove the declared flow */
2006
+ delete: operations["flowDeclaredDelete"];
2007
+ options?: never;
2008
+ head?: never;
2009
+ patch?: never;
2010
+ trace?: never;
2011
+ };
2012
+ "/api/tool/robots": {
2013
+ parameters: {
2014
+ query?: never;
2015
+ header?: never;
2016
+ path?: never;
2017
+ cookie?: never;
2018
+ };
2019
+ /** Resolve every named answer engine, search index and training crawler against a domain's robots.txt the way a crawler does: most-specific group only, longest match, allow wins a tie */
2020
+ get: operations["robotsResolve"];
2021
+ put?: never;
2022
+ post?: never;
2023
+ delete?: never;
2024
+ options?: never;
2025
+ head?: never;
2026
+ patch?: never;
2027
+ trace?: never;
2028
+ };
2029
+ "/api/tool/llms": {
2030
+ parameters: {
2031
+ query?: never;
2032
+ header?: never;
2033
+ path?: never;
2034
+ cookie?: never;
2035
+ };
2036
+ /** Draft an llms.txt from the domain's own homepage and up to 25 declared pages, using their titles and descriptions. A draft, not a publication */
2037
+ get: operations["llmsDraft"];
2038
+ put?: never;
2039
+ post?: never;
2040
+ delete?: never;
2041
+ options?: never;
2042
+ head?: never;
2043
+ patch?: never;
2044
+ trace?: never;
2045
+ };
2046
+ "/api/video": {
2047
+ parameters: {
2048
+ query?: never;
2049
+ header?: never;
2050
+ path?: never;
2051
+ cookie?: never;
2052
+ };
2053
+ /** One YouTube video against the video anchor model: twelve checks, each naming what it reads. Cached six hours */
2054
+ get: operations["videoCheck"];
2055
+ put?: never;
2056
+ post?: never;
2057
+ delete?: never;
2058
+ options?: never;
2059
+ head?: never;
2060
+ patch?: never;
2061
+ trace?: never;
2062
+ };
2063
+ "/api/video/channel": {
2064
+ parameters: {
2065
+ query?: never;
2066
+ header?: never;
2067
+ path?: never;
2068
+ cookie?: never;
2069
+ };
2070
+ /** Every upload on a channel, read 50 at a time. The upload list is free; the per-check tally (checks=1) is for Watch licences and above */
2071
+ get: operations["videoChannel"];
2072
+ put?: never;
2073
+ post?: never;
2074
+ delete?: never;
2075
+ options?: never;
2076
+ head?: never;
2077
+ patch?: never;
2078
+ trace?: never;
2079
+ };
2080
+ "/api/video/site": {
2081
+ parameters: {
2082
+ query?: never;
2083
+ header?: never;
2084
+ path?: never;
2085
+ cookie?: never;
2086
+ };
2087
+ /** The site half: homepage plus up to 60 sitemap pages read for YouTube embeds, facades and page-builder widgets, VideoObject nodes and their required properties, and - with a handle - how many of the channel's videos the site carries */
2088
+ get: operations["videoSite"];
2089
+ put?: never;
2090
+ post?: never;
2091
+ delete?: never;
2092
+ options?: never;
2093
+ head?: never;
2094
+ patch?: never;
2095
+ trace?: never;
2096
+ };
2097
+ "/api/fix/robots": {
2098
+ parameters: {
2099
+ query?: never;
2100
+ header?: never;
2101
+ path?: never;
2102
+ cookie?: never;
2103
+ };
2104
+ /** The served robots.txt, corrected: * group rules copied into every named group that lacked them, a Sitemap line added when the file never named the sitemap it serves, a minimal replacement when the served file was HTML. Every change is listed at the top of the file */
2105
+ get: operations["fixRobots"];
2106
+ put?: never;
2107
+ post?: never;
2108
+ delete?: never;
2109
+ options?: never;
2110
+ head?: never;
2111
+ patch?: never;
2112
+ trace?: never;
2113
+ };
2114
+ "/api/fix/entitymap": {
2115
+ parameters: {
2116
+ query?: never;
2117
+ header?: never;
2118
+ path?: never;
2119
+ cookie?: never;
2120
+ };
2121
+ /** A starter entitymap.json built from the latest scan record: name, phone, coordinates and every declared service area as entities with SERVES relations. Fields the page never stated are marked TODO, never guessed. Needs a prior scan */
2122
+ get: operations["fixEntitymap"];
2123
+ put?: never;
2124
+ post?: never;
2125
+ delete?: never;
2126
+ options?: never;
2127
+ head?: never;
2128
+ patch?: never;
2129
+ trace?: never;
2130
+ };
2131
+ "/api/entity/observe": {
2132
+ parameters: {
2133
+ query?: never;
2134
+ header?: never;
2135
+ path?: never;
2136
+ cookie?: never;
2137
+ };
2138
+ get?: never;
2139
+ put?: never;
2140
+ /** File a profile page as the owner's browser saw it, for the entity corroboration section. Consulted only where the scanner's own fetch was unverifiable; never overrides a live result; the row is labelled owner-browser. Licence-gated and bound to the licence's domains; the page's canonical must name the url's host. Kept 30 days */
2141
+ post: operations["entityObserve"];
2142
+ delete?: never;
2143
+ options?: never;
2144
+ head?: never;
2145
+ patch?: never;
2146
+ trace?: never;
2147
+ };
2148
+ "/api/public/counts": {
2149
+ parameters: {
2150
+ query?: never;
2151
+ header?: never;
2152
+ path?: never;
2153
+ cookie?: never;
2154
+ };
2155
+ /** The figures this site quotes about itself: sites_measured, domains_in_corpus (two different quantities), crawler_visits (a rolling window), queue, identities_sent, sections, sections_scored (derived from the weights map), findings_published, guides_published and an at timestamp. CORS open, cached 60 seconds */
2156
+ get: operations["publicCounts"];
2157
+ put?: never;
2158
+ post?: never;
2159
+ delete?: never;
2160
+ options?: never;
2161
+ head?: never;
2162
+ patch?: never;
2163
+ trace?: never;
2164
+ };
2165
+ "/api/registry": {
2166
+ parameters: {
2167
+ query?: never;
2168
+ header?: never;
2169
+ path?: never;
2170
+ cookie?: never;
2171
+ };
2172
+ /** The registry: which measured domains serve an llms.txt, an agents.md, a media kit, a reciprocity-tested entity graph, an AI access policy that names crawlers, or agent-callable surfaces */
2173
+ get: operations["registry"];
2174
+ put?: never;
2175
+ post?: never;
2176
+ delete?: never;
2177
+ options?: never;
2178
+ head?: never;
2179
+ patch?: never;
2180
+ trace?: never;
2181
+ };
2182
+ "/api/telemetry": {
2183
+ parameters: {
2184
+ query?: never;
2185
+ header?: never;
2186
+ path?: never;
2187
+ cookie?: never;
2188
+ };
2189
+ /** Verified-crawler telemetry observed at this origin */
2190
+ get: operations["telemetry"];
2191
+ put?: never;
2192
+ post?: never;
2193
+ delete?: never;
2194
+ options?: never;
2195
+ head?: never;
2196
+ patch?: never;
2197
+ trace?: never;
2198
+ };
2199
+ "/api/corpus/state": {
2200
+ parameters: {
2201
+ query?: never;
2202
+ header?: never;
2203
+ path?: never;
2204
+ cookie?: never;
2205
+ };
2206
+ /** Coverage of the public dataset by platform, rendering, size, language and kind */
2207
+ get: operations["corpusState"];
2208
+ put?: never;
2209
+ post?: never;
2210
+ delete?: never;
2211
+ options?: never;
2212
+ head?: never;
2213
+ patch?: never;
2214
+ trace?: never;
2215
+ };
2216
+ }
2217
+ export type webhooks = Record<string, never>;
2218
+ export interface components {
2219
+ schemas: {
2220
+ ScanRecord: {
2221
+ /** @description Report id; the report renders at /r/{id} and the record at /r/{id}.json */
2222
+ id?: string;
2223
+ domain?: string;
2224
+ /**
2225
+ * @description null when the origin refused the scanner or the scan could not be graded
2226
+ * @enum {string|null}
2227
+ */
2228
+ grade?: "A" | "B" | "C" | "D" | "F" | null;
2229
+ /** @description AI visibility: reach, then read, then quote */
2230
+ overall?: number | null;
2231
+ /** @description The homepage and a path that cannot exist answered identically: a wall, not a site. Nothing is scored */
2232
+ refused?: boolean;
2233
+ section_scores?: {
2234
+ id?: string;
2235
+ title?: string;
2236
+ score?: number | null;
2237
+ }[];
2238
+ findings?: {
2239
+ code?: string;
2240
+ severity?: number;
2241
+ path?: string;
2242
+ title?: string;
2243
+ detail?: string;
2244
+ evidence?: unknown;
2245
+ }[];
2246
+ /** @description Invariants checked on this record itself; a finding here is a defect in the scanner, never in the site */
2247
+ self_audit?: Record<string, never>;
2248
+ };
2249
+ VerifyResult: {
2250
+ tally?: {
2251
+ verified?: number;
2252
+ spoofed?: number;
2253
+ unverifiable?: number;
2254
+ no_bot?: number;
2255
+ };
2256
+ forged_rate_pct?: number | null;
2257
+ denominator_note?: string;
2258
+ rows?: Record<string, never>[];
2259
+ };
2260
+ PublicReportV1: {
2261
+ schema: string;
2262
+ /** @constant */
2263
+ version: "1.0";
2264
+ id: string | null;
2265
+ domain: string | null;
2266
+ path?: string | null;
2267
+ scanned_host?: string | null;
2268
+ scanned_at: string | null;
2269
+ score_version?: number | null;
2270
+ grade: string | null;
2271
+ overall: number | null;
2272
+ grade_detail?: {
2273
+ capped?: boolean;
2274
+ cap?: string | null;
2275
+ cap_reason?: string | null;
2276
+ };
2277
+ sections: {
2278
+ id?: string | null;
2279
+ title?: string | null;
2280
+ /** @description null means not measured, never zero */
2281
+ score?: number | null;
2282
+ }[];
2283
+ findings: {
2284
+ code?: string | null;
2285
+ path?: string | null;
2286
+ severity?: number | null;
2287
+ title?: string | null;
2288
+ detail?: string | null;
2289
+ meaning?: string | null;
2290
+ evidence?: string | null;
2291
+ fid?: string | null;
2292
+ decision_id?: string | null;
2293
+ graph?: string | null;
2294
+ /** @description true on an unlicensed read for every finding but the top one: title, severity and path are present, the rest is withheld */
2295
+ locked?: boolean;
2296
+ /** @description code|path; stable across scans of the same domain; null on a locked finding */
2297
+ fingerprint?: string | null;
2298
+ /**
2299
+ * @description lifecycle on this scan; null when the domain has no stored history
2300
+ * @enum {string|null}
2301
+ */
2302
+ state?: "new" | "persisted" | "worsened" | "improved" | "regressed" | "resolved" | "rule-changed" | null;
2303
+ first_seen?: string | null;
2304
+ scans_seen?: number | null;
2305
+ recurrences?: number | null;
2306
+ /** @description bitemporal: when the condition held on the site (valid_from / valid_to as after-by intervals between observations; null ends are unknown or still open) and when CrawlCheck recorded it (recorded_at, superseded_at) */
2307
+ valid_time?: Record<string, never> | null;
2308
+ }[];
2309
+ /** @description Set on an unlicensed read: every finding is listed by title, severity and path; detail, evidence and code beyond the top one are withheld */
2310
+ findings_withheld?: string | null;
2311
+ findings_summary?: {
2312
+ total?: number | null;
2313
+ serious?: number | null;
2314
+ by_severity?: Record<string, never> | null;
2315
+ } | null;
2316
+ /** @description Observer build, vantage, rule version, observed and stored times, sealed manifest */
2317
+ provenance?: Record<string, never> | null;
2318
+ /** @description Findings that share one cause or one fix, formed only from evidence in this record (e.g. robots.txt, the sitemap and llms.txt all answering with the site's HTML page). With a licence: cause, fix, generators, evidence and members. An unlicensed v1 read is built from the locked record, so the list is empty there; /api/v1/machine-record shows a group the top finding belongs to, by kind and size */
2319
+ root_causes?: unknown[] | null;
2320
+ /** @description One line per fix that would change this record (robots, sitemap, llms, entitymap, edge-bots, cache, page-code, chain, hsts, host-pair), best first: findings and rows it clears, the other fixes some of its rows also need, the score and letter after (the formula rerun), root causes it closes and certificate criteria it flips. Null on an unlicensed read; /api/impact has the names */
2321
+ fix_impact?: unknown[] | null;
2322
+ /** @description combined {all_rows_fixed, all_findings_cleared, both} and next_letter {target, reachable, ...} are recomputed, never summed. What each decision moved. rows[]: every failing scored row with points = the score recomputed with that row passing minus the score now (same formula, Reach + 15 ceiling included), points_section_average, and why a row moves nothing; withheld (rows_withheld) where the fix list is. Findings move no points: each finding's score_effect states the letter cap it sets, whether it binds, and the letter without it. */
2323
+ score_ledger?: Record<string, never> | null;
2324
+ /** @description Counts and ratios behind the reading: sections_scored, identities_answered, fetches_kept, stage_failures, non_observations, vantages. No composite number, because the parts do not combine into one honestly */
2325
+ confidence?: Record<string, never> | null;
2326
+ /** @description Each stated fact with two times: when CrawlCheck observed it (observed_from, observed_last, removed_at) and when the site says it became true (valid time, null when the site does not say) */
2327
+ bitemporal?: Record<string, never> | null;
2328
+ /** @description What was not measured on this scan and why; an unmeasured subject is never scored as a pass or a fail */
2329
+ non_observations?: {
2330
+ subject?: string | null;
2331
+ state?: string | null;
2332
+ reason?: string | null;
2333
+ attempted?: boolean | null;
2334
+ }[] | null;
2335
+ /** @description Each value carries locators[] (one per source): bytes [start, end) in the page this scan received, line, col, scope (meta[og:title], script[ld+json]#0, title, page text) and match (value | property | normalised | partial), or {found:false, why}; check them with /api/locate. Each business fact (name, phone, address, email, founder) with every value the site stated and where it stated it, and whether the statements agree */
2336
+ fact_lineage?: Record<string, never> | null;
2337
+ checks?: {
2338
+ path?: string | null;
2339
+ status?: number | null;
2340
+ bytes?: number | null;
2341
+ }[];
2342
+ agentview?: {
2343
+ label?: string | null;
2344
+ status?: number | null;
2345
+ words?: number | null;
2346
+ }[];
2347
+ nap?: Record<string, never> | null;
2348
+ headroom?: {
2349
+ gain?: number | null;
2350
+ failing?: number | null;
2351
+ } | null;
2352
+ history?: {
2353
+ at?: string | null;
2354
+ overall?: number | null;
2355
+ score_version?: number | null;
2356
+ }[];
2357
+ proof: {
2358
+ digest?: string | null;
2359
+ algorithm?: string | null;
2360
+ anchored?: string | null;
2361
+ verify?: string | null;
2362
+ };
2363
+ links?: Record<string, never>;
2364
+ };
2365
+ /** @description One observation in one shape (GET /api/v1/machine-record, MCP machine_record): subject, observation, findings (top in full without a licence; the rest locked), capabilities with safety class and verification state, evidence roots and verifier links */
2366
+ MachineRecordV1: {
2367
+ /** @constant */
2368
+ kind: "crawlcheck-machine-record";
2369
+ version: string;
2370
+ subject: Record<string, never>;
2371
+ observation: Record<string, never>;
2372
+ /** @description each open finding carries trust {freshness, confidence {level, means, basis[]}, contradictions[]} */
2373
+ findings: unknown[];
2374
+ /** @description observed_at, age_hours, latest_report_id, is_latest, newer_scan_exists, last_second_reading_at */
2375
+ freshness?: Record<string, never>;
2376
+ /** @description With a licence: one line per fix that would change this record, best first (findings and rows it clears, other fixes some rows also need, score and letter after, root causes closed, certificate criteria flipped). Without: {fixes_available, best_single_fix {letter_after, score_after, findings_cleared, rows_cleared}} and no names */
2377
+ fix_impact?: unknown[] | Record<string, never> | null;
2378
+ /** @description score, letter, cap and the points each failing row moves (rows open with a licence); each open finding carries score_effect {points: 0, cap, binding, letter_without_it, says} */
2379
+ score_ledger?: Record<string, never> | null;
2380
+ /** @description counts and ratios plus vantages; no composite number; levels: contested | cross_vantage_confirmed | reproduced | single_reading */
2381
+ confidence?: Record<string, never>;
2382
+ /** @description site (the site contradicts itself) and between_networks_open (observers disagree), for findings this caller can open */
2383
+ contradictions?: Record<string, never>;
2384
+ findings_summary?: Record<string, never> | null;
2385
+ findings_withheld?: string | null;
2386
+ capabilities: Record<string, never>;
2387
+ evidence: Record<string, never>;
2388
+ access: Record<string, never>;
2389
+ };
2390
+ ErrorV1: {
2391
+ error: {
2392
+ code: string;
2393
+ status?: number;
2394
+ message: string;
2395
+ };
2396
+ };
2397
+ /** @description GET /api/bundle: one file that checks offline with /crawlcheck-verify.mjs. A field that cannot be filled (an anonymous download, an unsealed day, a record from before manifests) is null with a *_withheld / *_missing / why reason, never omitted */
2398
+ EvidenceBundleV1: {
2399
+ /** @constant */
2400
+ kind: "crawlcheck-evidence-bundle";
2401
+ version: number;
2402
+ generated_at?: string;
2403
+ report: {
2404
+ id: string | null;
2405
+ domain: string | null;
2406
+ path?: string | null;
2407
+ scanned_at: string | null;
2408
+ score_version?: number | null;
2409
+ archived?: boolean;
2410
+ };
2411
+ verifier: {
2412
+ url: string;
2413
+ sha256: string;
2414
+ run?: string;
2415
+ page?: string;
2416
+ };
2417
+ proves?: string[];
2418
+ does_not_prove?: string[];
2419
+ manifest: {
2420
+ sha256: string;
2421
+ body: string | null;
2422
+ body_missing?: string | null;
2423
+ signature?: {
2424
+ alg?: string | null;
2425
+ kid?: string | null;
2426
+ message?: string | null;
2427
+ sig?: string | null;
2428
+ signed_at?: string | null;
2429
+ } | null;
2430
+ key?: {
2431
+ jwk?: {
2432
+ /** @constant */
2433
+ kty: "OKP";
2434
+ /** @constant */
2435
+ crv: "Ed25519";
2436
+ x: string;
2437
+ };
2438
+ kid?: string;
2439
+ published_in?: string;
2440
+ } | null;
2441
+ key_missing?: string | null;
2442
+ } | null;
2443
+ record: {
2444
+ digest: string | null;
2445
+ subject: string | null;
2446
+ subject_withheld?: string | null;
2447
+ recipe?: string | null;
2448
+ decision_leaves?: Record<string, never>[] | null;
2449
+ lineage_leaves?: Record<string, never>[] | null;
2450
+ leaves_withheld?: string | null;
2451
+ } | null;
2452
+ seal: {
2453
+ /** @enum {unknown} */
2454
+ state: "sealed" | "pending" | "unsealed" | "unverifiable" | "unknown";
2455
+ day?: string | null;
2456
+ root?: string | null;
2457
+ path?: {
2458
+ /** @enum {unknown} */
2459
+ side: "left" | "right";
2460
+ hash: string;
2461
+ }[];
2462
+ leaves_that_day?: number | null;
2463
+ sealed_at?: string | null;
2464
+ calendars?: string[];
2465
+ ots_base64?: string | null;
2466
+ bitcoin_block?: number | null;
2467
+ recipe?: string | null;
2468
+ why?: string | null;
2469
+ } | null;
2470
+ /** @description sec8: every bundle is scanned before it is served; a section that matched is null and carries <section>_withheld */
2471
+ publish_guard?: {
2472
+ checked?: string[];
2473
+ withheld?: {
2474
+ section?: string;
2475
+ matched?: string[];
2476
+ }[];
2477
+ };
2478
+ /** @description Who can read which representation of a scan: /docs/api#disclosure */
2479
+ disclosure?: string;
2480
+ } & {
2481
+ [key: string]: string;
2482
+ };
2483
+ /** @description A signed remediation receipt (GET /api/receipt?id=). receipt_id = rc1: + sha256 of the canonical JSON of every field except receipt_id and signature; signature = Ed25519 over 'crawlcheck-receipt-v1\n' + that sha256 */
2484
+ RemediationReceiptV1: {
2485
+ receipt_id: string;
2486
+ /** @constant */
2487
+ kind: "crawlcheck-remediation-receipt";
2488
+ /** @constant */
2489
+ v: 1;
2490
+ issued_at: string;
2491
+ issuer: {
2492
+ observer?: string | null;
2493
+ version_id?: string | null;
2494
+ version_tag?: string | null;
2495
+ key: {
2496
+ kid: string;
2497
+ jwk: Record<string, never>;
2498
+ published_in?: string | null;
2499
+ };
2500
+ };
2501
+ subject: {
2502
+ domain: string;
2503
+ };
2504
+ before: components["schemas"]["ReceiptSideV1"];
2505
+ after: components["schemas"]["ReceiptSideV1"];
2506
+ declared_fix: {
2507
+ kind?: string;
2508
+ declared_by?: string | null;
2509
+ declared_at?: string | null;
2510
+ plugin_version?: string | null;
2511
+ fixes?: string[] | null;
2512
+ note?: string | null;
2513
+ };
2514
+ deployed: {
2515
+ at?: string | null;
2516
+ basis?: string | null;
2517
+ };
2518
+ verification: {
2519
+ /** @enum {unknown} */
2520
+ verdict: "improved" | "unchanged" | "mixed" | "regressed";
2521
+ summary?: string | null;
2522
+ comparable?: boolean;
2523
+ findings?: Record<string, never>;
2524
+ rows?: Record<string, never>;
2525
+ files?: {
2526
+ path?: string;
2527
+ state?: string;
2528
+ before_sha256?: string | null;
2529
+ after_sha256?: string | null;
2530
+ before_status?: number | null;
2531
+ after_status?: number | null;
2532
+ }[];
2533
+ rollback_needed?: boolean;
2534
+ rollback_steps?: Record<string, never>[];
2535
+ method?: string | null;
2536
+ };
2537
+ links?: Record<string, never>;
2538
+ signature: {
2539
+ v?: number | null;
2540
+ /** @constant */
2541
+ alg: "Ed25519";
2542
+ kid: string;
2543
+ over?: string | null;
2544
+ receipt_sha256: string;
2545
+ message: string;
2546
+ sig: string;
2547
+ signed_at?: string | null;
2548
+ canonical?: string | null;
2549
+ };
2550
+ };
2551
+ /** @description tr1: one scan's trace (GET /api/trace?id=, owner; sampled by the trace CI job). W3C Trace Context ids. Every span's parent is the scan span (root_span_id) or a span of this trace; the scan span's own parent is the caller's span when the scan joined a caller's trace (parent). */
2552
+ TraceV1: {
2553
+ id: string | null;
2554
+ domain?: string | null;
2555
+ scanned_at?: string | null;
2556
+ traced: boolean;
2557
+ why?: string | null;
2558
+ trace_id?: string;
2559
+ root_span_id?: string;
2560
+ traceparent?: string;
2561
+ parent?: {
2562
+ span_id?: string;
2563
+ source?: string | null;
2564
+ previous_trace_id?: string | null;
2565
+ } | null;
2566
+ scan_id?: string | null;
2567
+ started_at?: string | null;
2568
+ total_ms?: number | null;
2569
+ dropped?: number;
2570
+ recorded_through?: unknown;
2571
+ spans?: components["schemas"]["SpanV1"][];
2572
+ errors?: {
2573
+ error_id?: string | null;
2574
+ stage?: string | null;
2575
+ span_id: string | null;
2576
+ error?: string | null;
2577
+ }[];
2578
+ findings?: {
2579
+ code?: string | null;
2580
+ decision_id?: string | null;
2581
+ span_id?: string | null;
2582
+ parent_span_id?: string | null;
2583
+ parent_stage?: string | null;
2584
+ reads?: number | null;
2585
+ }[];
2586
+ coverage?: Record<string, never>;
2587
+ slowest?: unknown[];
2588
+ decisions_with_spans?: number | null;
2589
+ note?: string | null;
2590
+ } & unknown;
2591
+ /** @description tr1: one span: a stage of the scan, or (kind rule) one decision, started when its rule decided. */
2592
+ SpanV1: {
2593
+ span_id: string;
2594
+ parent_span_id: string;
2595
+ stage: string;
2596
+ /** @enum {unknown} */
2597
+ kind?: "rule";
2598
+ start_ms: number;
2599
+ dur_ms?: number | null;
2600
+ /** @enum {unknown} */
2601
+ status: "ok" | "error" | "inputs_disputed";
2602
+ error_id?: string | null;
2603
+ code?: string | null;
2604
+ path?: string | null;
2605
+ decision_id?: string | null;
2606
+ reads?: {
2607
+ experience_id?: string | null;
2608
+ fetched_in?: string | null;
2609
+ stage?: string | null;
2610
+ fetched_after_rule?: boolean;
2611
+ }[];
2612
+ parent_basis?: string | null;
2613
+ };
2614
+ /** @description dsp1: a signed resolution of a dispute against one finding (GET /api/disputes/resolution?id=). Verifies offline with crawlcheck-verify.mjs: hash, key id, Ed25519 signature, and the verdict re-derived from the recorded readings by the published decision table. */
2615
+ DisputeResolutionV1: {
2616
+ resolution_id: string;
2617
+ /** @constant */
2618
+ kind: "crawlcheck-dispute-resolution";
2619
+ /** @constant */
2620
+ v: 1;
2621
+ schema?: string | null;
2622
+ dispute_id: string;
2623
+ issued_at: string;
2624
+ issuer: {
2625
+ observer?: string | null;
2626
+ version_id?: string | null;
2627
+ version_tag?: string | null;
2628
+ key?: {
2629
+ kid?: string;
2630
+ jwk?: Record<string, never>;
2631
+ published_in?: string;
2632
+ };
2633
+ };
2634
+ subject: {
2635
+ domain: string;
2636
+ record: Record<string, never>;
2637
+ finding: {
2638
+ code?: string;
2639
+ path?: string | null;
2640
+ fid?: string | null;
2641
+ decision_id?: string | null;
2642
+ title?: string | null;
2643
+ severity?: number | null;
2644
+ rule_revision?: number | null;
2645
+ };
2646
+ };
2647
+ dispute: {
2648
+ filed_at?: string;
2649
+ /** @enum {unknown} */
2650
+ ground?: "misread" | "fixed" | "network" | "rule";
2651
+ ground_text?: string | null;
2652
+ statement?: string;
2653
+ ownership?: {
2654
+ method?: string;
2655
+ at?: string;
2656
+ url?: string | null;
2657
+ sha256?: string | null;
2658
+ } | null;
2659
+ };
2660
+ remeasurement: {
2661
+ replay: {
2662
+ reproduces?: boolean | null;
2663
+ rule?: string | null;
2664
+ read?: unknown;
2665
+ why?: string | null;
2666
+ rule_revision?: number | null;
2667
+ over?: string | null;
2668
+ };
2669
+ observers: {
2670
+ /** @enum {unknown} */
2671
+ role: "primary" | "independent";
2672
+ observer_id: string;
2673
+ network_class?: string | null;
2674
+ network?: string | null;
2675
+ at?: string | null;
2676
+ finding_present: boolean | null;
2677
+ inputs_agree?: boolean | null;
2678
+ method?: string | null;
2679
+ reading?: string | null;
2680
+ side?: Record<string, never> | null;
2681
+ observation?: Record<string, never> | null;
2682
+ }[];
2683
+ deadline?: string | null;
2684
+ independent_wait_hours?: number | null;
2685
+ };
2686
+ decision: {
2687
+ /** @enum {unknown} */
2688
+ verdict: "upheld" | "corrected" | "fixed_since" | "vantage_dependent" | "no_longer_observed" | "inconclusive";
2689
+ verdict_text?: string | null;
2690
+ /** @enum {unknown} */
2691
+ effect: "stands" | "withdrawn" | "stands_for_record" | "stands_with_scope" | "stands_unresolved";
2692
+ effect_text?: string | null;
2693
+ rule?: string | null;
2694
+ table?: string | null;
2695
+ derived_by?: string | null;
2696
+ };
2697
+ links?: Record<string, never>;
2698
+ signature: {
2699
+ /** @constant */
2700
+ v?: 1;
2701
+ /** @constant */
2702
+ alg: "Ed25519";
2703
+ kid: string;
2704
+ /** @constant */
2705
+ over?: "resolution_sha256";
2706
+ resolution_sha256: string;
2707
+ message: string;
2708
+ sig: string;
2709
+ signed_at?: string;
2710
+ canonical?: string;
2711
+ };
2712
+ };
2713
+ /** @description Every finding the scanner can raise (GET /api/rules): what it means, its level, its fix and its share of counted scans. */
2714
+ RulebookV1: {
2715
+ ok?: boolean;
2716
+ /** @constant */
2717
+ kind: "crawlcheck-rulebook";
2718
+ /** @constant */
2719
+ v: 1;
2720
+ generated_at: string;
2721
+ score_version?: number | null;
2722
+ schema?: string | null;
2723
+ counts: {
2724
+ rules: number;
2725
+ by_kind?: {
2726
+ [key: string]: number;
2727
+ };
2728
+ by_family?: {
2729
+ [key: string]: number;
2730
+ };
2731
+ revised?: number;
2732
+ scored?: number;
2733
+ };
2734
+ scans_counted?: number | null;
2735
+ severity_scale: {
2736
+ level?: string;
2737
+ }[];
2738
+ method?: {
2739
+ revisions?: string | null;
2740
+ share?: string | null;
2741
+ grade?: string | null;
2742
+ };
2743
+ /** @description every rule; with ?code= only that rule (counts still describe the whole rulebook) */
2744
+ rules: components["schemas"]["RuleV1"][];
2745
+ filter?: {
2746
+ code?: string | null;
2747
+ } | null;
2748
+ };
2749
+ /** @description One rule: the code, what it means, its level, its current revision, its fix and its share of counted scans. */
2750
+ RuleV1: {
2751
+ code: string;
2752
+ /**
2753
+ * @description self_audit: a defect in CrawlCheck's own record, never in the site
2754
+ * @enum {unknown}
2755
+ */
2756
+ kind: "scan" | "answer_correlation" | "capability_mismatch" | "self_audit";
2757
+ family: {
2758
+ id: string;
2759
+ label: string;
2760
+ };
2761
+ title: string | null;
2762
+ meaning?: string | null;
2763
+ severity: {
2764
+ level?: string | null;
2765
+ };
2766
+ /** @description raised on a graded scan record; refusals, answer runs, capability mismatches and self-audit findings are not */
2767
+ scored?: boolean;
2768
+ measured_on?: string | null;
2769
+ revision: {
2770
+ current: number;
2771
+ /** @description when the current revision took effect; null while the rule is at revision 1 */
2772
+ revised_at?: string | null;
2773
+ };
2774
+ fix?: {
2775
+ advice?: string | null;
2776
+ effort?: string | null;
2777
+ endpoint?: string | null;
2778
+ };
2779
+ share_of_scans: {
2780
+ pct: number | null;
2781
+ scans?: number | null;
2782
+ of_scans?: number | null;
2783
+ basis: string;
2784
+ };
2785
+ links?: {
2786
+ self?: string | null;
2787
+ api?: string | null;
2788
+ glossary?: string[];
2789
+ workflow?: string | null;
2790
+ lineage?: string | null;
2791
+ explain_template?: string | null;
2792
+ };
2793
+ };
2794
+ /** @description What the owner's connected outcome sources counted either side of a receipt's anchor day (GET /api/outcomes). One series per named source; per-day values compared; a series with no source is connected:false with how_to_connect; a window under 7 measured days is usable:false with why. Never a claim of cause. */
2795
+ FixOutcomesV1: {
2796
+ ok?: boolean;
2797
+ /** @constant */
2798
+ kind: "crawlcheck-fix-outcomes";
2799
+ /** @constant */
2800
+ v: 1;
2801
+ generated_at?: string;
2802
+ cached?: boolean;
2803
+ receipt: {
2804
+ id: string;
2805
+ domain: string;
2806
+ verdict?: string | null;
2807
+ findings_cleared?: string[];
2808
+ url?: string;
2809
+ anchor: {
2810
+ at?: string;
2811
+ /** Format: date */
2812
+ day: string;
2813
+ basis: string;
2814
+ };
2815
+ };
2816
+ window: {
2817
+ days: number;
2818
+ before: {
2819
+ from?: string | null;
2820
+ to?: string | null;
2821
+ };
2822
+ after: {
2823
+ from?: string | null;
2824
+ to?: string | null;
2825
+ days_elapsed?: number;
2826
+ complete?: boolean;
2827
+ };
2828
+ };
2829
+ connected: number;
2830
+ usable: number;
2831
+ series: {
2832
+ key: string;
2833
+ label: string;
2834
+ source: string;
2835
+ /** @enum {unknown} */
2836
+ mode: "daily" | "events";
2837
+ connected: boolean;
2838
+ note?: string;
2839
+ how_to_connect?: string | null;
2840
+ before?: components["schemas"]["OutcomeSideV1"] | null;
2841
+ after?: components["schemas"]["OutcomeSideV1"] | null;
2842
+ delta_per_day?: number | null;
2843
+ pct?: number | null;
2844
+ usable: boolean;
2845
+ why: string;
2846
+ }[];
2847
+ not_measured?: {
2848
+ key?: string;
2849
+ why?: string;
2850
+ }[];
2851
+ summary?: string;
2852
+ reading?: string;
2853
+ not_proof: string;
2854
+ how_to_cite?: string;
2855
+ };
2856
+ OutcomeSideV1: {
2857
+ from?: string | null;
2858
+ to?: string | null;
2859
+ days: number;
2860
+ measured: number;
2861
+ sum: number;
2862
+ per_day: number | null;
2863
+ };
2864
+ ReceiptSideV1: {
2865
+ report_id: string | null;
2866
+ scanned_at: string | null;
2867
+ grade?: string | null;
2868
+ score?: number | null;
2869
+ score_version?: number | null;
2870
+ refused?: boolean;
2871
+ findings?: number | null;
2872
+ manifest_sha256?: string | null;
2873
+ decision_root?: string | null;
2874
+ trace_id?: string | null;
2875
+ };
2876
+ };
2877
+ responses: never;
2878
+ parameters: never;
2879
+ requestBodies: never;
2880
+ headers: never;
2881
+ pathItems: never;
2882
+ }
2883
+ export type $defs = Record<string, never>;
2884
+ export interface operations {
2885
+ scan: {
2886
+ parameters: {
2887
+ query?: never;
2888
+ header?: never;
2889
+ path?: never;
2890
+ cookie?: never;
2891
+ };
2892
+ requestBody: {
2893
+ content: {
2894
+ "application/json": {
2895
+ /**
2896
+ * @description A bare domain or a full URL
2897
+ * @example example.com
2898
+ */
2899
+ domain: string;
2900
+ /**
2901
+ * @description unlisted: the report is reachable only by its link; the scan is sealed and archived but enters no public registry, dataset, history or resolve answer. private: needs a licence for the domain (or the owner); the report opens only for that licence holder or the owner and is not archived or listed anywhere (default public)
2902
+ * @enum {unknown}
2903
+ */
2904
+ visibility?: "public" | "unlisted" | "private";
2905
+ };
2906
+ };
2907
+ };
2908
+ responses: {
2909
+ /** @description The scan record */
2910
+ 200: {
2911
+ headers: {
2912
+ [name: string]: unknown;
2913
+ };
2914
+ content: {
2915
+ "application/json": components["schemas"]["ScanRecord"];
2916
+ };
2917
+ };
2918
+ /** @description Not a public domain (reserved names such as .example and .invalid included), or no JSON body */
2919
+ 400: {
2920
+ headers: {
2921
+ [name: string]: unknown;
2922
+ };
2923
+ content?: never;
2924
+ };
2925
+ /** @description Rate limited: 5 requests per 10 seconds per address; a scan of the same domain still running (code scan_in_progress); or the daily total of free scans reached (code daily_budget). Retry-After says when. A rescan of a domain scanned in the last 2 minutes returns that report (field cached) instead of fetching the site again; a domain where nothing answered returns 200 with unreachable: true, id: null and nothing stored */
2926
+ 429: {
2927
+ headers: {
2928
+ [name: string]: unknown;
2929
+ };
2930
+ content?: never;
2931
+ };
2932
+ /** @description Free scans paused (code scans_paused); keyed scans are unaffected */
2933
+ 503: {
2934
+ headers: {
2935
+ [name: string]: unknown;
2936
+ };
2937
+ content?: never;
2938
+ };
2939
+ };
2940
+ };
2941
+ scanDomainV1: {
2942
+ parameters: {
2943
+ query?: never;
2944
+ header?: never;
2945
+ path?: never;
2946
+ cookie?: never;
2947
+ };
2948
+ requestBody: {
2949
+ content: {
2950
+ "application/json": {
2951
+ domain: string;
2952
+ };
2953
+ };
2954
+ };
2955
+ responses: {
2956
+ /** @description PublicReportV1 */
2957
+ 200: {
2958
+ headers: {
2959
+ [name: string]: unknown;
2960
+ };
2961
+ content: {
2962
+ "application/json": components["schemas"]["PublicReportV1"];
2963
+ };
2964
+ };
2965
+ /** @description ErrorV1: bad_request */
2966
+ 400: {
2967
+ headers: {
2968
+ [name: string]: unknown;
2969
+ };
2970
+ content?: never;
2971
+ };
2972
+ /** @description ErrorV1: rate_limited */
2973
+ 429: {
2974
+ headers: {
2975
+ [name: string]: unknown;
2976
+ };
2977
+ content?: never;
2978
+ };
2979
+ };
2980
+ };
2981
+ reportAgentOutcomeV1: {
2982
+ parameters: {
2983
+ query?: never;
2984
+ header?: never;
2985
+ path?: never;
2986
+ cookie?: never;
2987
+ };
2988
+ requestBody?: never;
2989
+ responses: {
2990
+ /** @description accepted */
2991
+ 202: {
2992
+ headers: {
2993
+ [name: string]: unknown;
2994
+ };
2995
+ content: {
2996
+ "application/json": unknown;
2997
+ };
2998
+ };
2999
+ /** @description invalid report */
3000
+ 400: {
3001
+ headers: {
3002
+ [name: string]: unknown;
3003
+ };
3004
+ content?: never;
3005
+ };
3006
+ /** @description 500 reports a day per address */
3007
+ 429: {
3008
+ headers: {
3009
+ [name: string]: unknown;
3010
+ };
3011
+ content?: never;
3012
+ };
1796
3013
  };
1797
- PublicReportV1: {
1798
- schema: string;
1799
- /** @constant */
1800
- version: "1.0";
1801
- id: string | null;
1802
- domain: string | null;
1803
- path?: string | null;
1804
- scanned_host?: string | null;
1805
- scanned_at: string | null;
1806
- score_version?: number | null;
1807
- grade: string | null;
1808
- overall: number | null;
1809
- grade_detail?: {
1810
- capped?: boolean;
1811
- cap?: string | null;
1812
- cap_reason?: string | null;
3014
+ };
3015
+ agentOutcomesV1: {
3016
+ parameters: {
3017
+ query: {
3018
+ domain: string;
1813
3019
  };
1814
- sections: {
1815
- id?: string | null;
1816
- title?: string | null;
1817
- /** @description null means not measured, never zero */
1818
- score?: number | null;
1819
- }[];
1820
- findings: {
1821
- code?: string | null;
1822
- path?: string | null;
1823
- severity?: number | null;
1824
- title?: string | null;
1825
- detail?: string | null;
1826
- meaning?: string | null;
1827
- evidence?: string | null;
1828
- fid?: string | null;
1829
- decision_id?: string | null;
1830
- graph?: string | null;
1831
- /** @description true on an unlicensed read for every finding but the top one: title, severity and path are present, the rest is withheld */
1832
- locked?: boolean;
1833
- /** @description code|path; stable across scans of the same domain; null on a locked finding */
1834
- fingerprint?: string | null;
1835
- /**
1836
- * @description lifecycle on this scan; null when the domain has no stored history
1837
- * @enum {string|null}
1838
- */
1839
- state?: "new" | "persisted" | "worsened" | "improved" | "regressed" | "resolved" | "rule-changed" | null;
1840
- first_seen?: string | null;
1841
- scans_seen?: number | null;
1842
- recurrences?: number | null;
1843
- /** @description bitemporal: when the condition held on the site (valid_from / valid_to as after-by intervals between observations; null ends are unknown or still open) and when CrawlCheck recorded it (recorded_at, superseded_at) */
1844
- valid_time?: Record<string, never> | null;
1845
- }[];
1846
- /** @description Set on an unlicensed read: every finding is listed by title, severity and path; detail, evidence and code beyond the top one are withheld */
1847
- findings_withheld?: string | null;
1848
- findings_summary?: {
1849
- total?: number | null;
1850
- serious?: number | null;
1851
- by_severity?: Record<string, never> | null;
1852
- } | null;
1853
- /** @description Observer build, vantage, rule version, observed and stored times, sealed manifest */
1854
- provenance?: Record<string, never> | null;
1855
- /** @description Findings that share one cause or one fix, formed only from evidence in this record (e.g. robots.txt, the sitemap and llms.txt all answering with the site's HTML page). With a licence: cause, fix, generators, evidence and members. An unlicensed v1 read is built from the locked record, so the list is empty there; /api/v1/machine-record shows a group the top finding belongs to, by kind and size */
1856
- root_causes?: unknown[] | null;
1857
- /** @description One line per fix that would change this record (robots, sitemap, llms, entitymap, edge-bots, cache, page-code, chain, hsts, host-pair), best first: findings and rows it clears, the other fixes some of its rows also need, the score and letter after (the formula rerun), root causes it closes and certificate criteria it flips. Null on an unlicensed read; /api/impact has the names */
1858
- fix_impact?: unknown[] | null;
1859
- /** @description combined {all_rows_fixed, all_findings_cleared, both} and next_letter {target, reachable, ...} are recomputed, never summed. What each decision moved. rows[]: every failing scored row with points = the score recomputed with that row passing minus the score now (same formula, Reach + 15 ceiling included), points_section_average, and why a row moves nothing; withheld (rows_withheld) where the fix list is. Findings move no points: each finding's score_effect states the letter cap it sets, whether it binds, and the letter without it. */
1860
- score_ledger?: Record<string, never> | null;
1861
- /** @description Counts and ratios behind the reading: sections_scored, identities_answered, fetches_kept, stage_failures, non_observations, vantages. No composite number, because the parts do not combine into one honestly */
1862
- confidence?: Record<string, never> | null;
1863
- /** @description Each stated fact with two times: when CrawlCheck observed it (observed_from, observed_last, removed_at) and when the site says it became true (valid time, null when the site does not say) */
1864
- bitemporal?: Record<string, never> | null;
1865
- /** @description What was not measured on this scan and why; an unmeasured subject is never scored as a pass or a fail */
1866
- non_observations?: {
1867
- subject?: string | null;
1868
- state?: string | null;
1869
- reason?: string | null;
1870
- attempted?: boolean | null;
1871
- }[] | null;
1872
- /** @description Each value carries locators[] (one per source): bytes [start, end) in the page this scan received, line, col, scope (meta[og:title], script[ld+json]#0, title, page text) and match (value | property | normalised | partial), or {found:false, why}; check them with /api/locate. Each business fact (name, phone, address, email, founder) with every value the site stated and where it stated it, and whether the statements agree */
1873
- fact_lineage?: Record<string, never> | null;
1874
- checks?: {
1875
- path?: string | null;
1876
- status?: number | null;
1877
- bytes?: number | null;
1878
- }[];
1879
- agentview?: {
1880
- label?: string | null;
1881
- status?: number | null;
1882
- words?: number | null;
1883
- }[];
1884
- nap?: Record<string, never> | null;
1885
- headroom?: {
1886
- gain?: number | null;
1887
- failing?: number | null;
1888
- } | null;
1889
- history?: {
1890
- at?: string | null;
1891
- overall?: number | null;
1892
- score_version?: number | null;
1893
- }[];
1894
- proof: {
1895
- digest?: string | null;
1896
- algorithm?: string | null;
1897
- anchored?: string | null;
1898
- verify?: string | null;
3020
+ header?: never;
3021
+ path?: never;
3022
+ cookie?: never;
3023
+ };
3024
+ requestBody?: never;
3025
+ responses: {
3026
+ /** @description crawlcheck-agent-outcomes */
3027
+ 200: {
3028
+ headers: {
3029
+ [name: string]: unknown;
3030
+ };
3031
+ content: {
3032
+ "application/json": unknown;
3033
+ };
3034
+ };
3035
+ };
3036
+ };
3037
+ aiAccuracyV1: {
3038
+ parameters: {
3039
+ query: {
3040
+ domain: string;
3041
+ };
3042
+ header?: never;
3043
+ path?: never;
3044
+ cookie?: never;
3045
+ };
3046
+ requestBody?: never;
3047
+ responses: {
3048
+ /** @description crawlcheck-ai-accuracy */
3049
+ 200: {
3050
+ headers: {
3051
+ [name: string]: unknown;
3052
+ };
3053
+ content: {
3054
+ "application/json": unknown;
3055
+ };
3056
+ };
3057
+ /** @description not tracked or not measured */
3058
+ 404: {
3059
+ headers: {
3060
+ [name: string]: unknown;
3061
+ };
3062
+ content?: never;
3063
+ };
3064
+ };
3065
+ };
3066
+ domainLifecycleV1: {
3067
+ parameters: {
3068
+ query: {
3069
+ domain: string;
3070
+ };
3071
+ header?: never;
3072
+ path?: never;
3073
+ cookie?: never;
3074
+ };
3075
+ requestBody?: never;
3076
+ responses: {
3077
+ /** @description crawlcheck-domain */
3078
+ 200: {
3079
+ headers: {
3080
+ [name: string]: unknown;
3081
+ };
3082
+ content: {
3083
+ "application/json": unknown;
3084
+ };
3085
+ };
3086
+ };
3087
+ };
3088
+ visitorResolveV1: {
3089
+ parameters: {
3090
+ query: {
3091
+ ip?: string;
3092
+ ua: string;
3093
+ };
3094
+ header?: never;
3095
+ path?: never;
3096
+ cookie?: never;
3097
+ };
3098
+ requestBody?: never;
3099
+ responses: {
3100
+ /** @description crawlcheck-visitor */
3101
+ 200: {
3102
+ headers: {
3103
+ [name: string]: unknown;
3104
+ };
3105
+ content: {
3106
+ "application/json": unknown;
3107
+ };
3108
+ };
3109
+ };
3110
+ };
3111
+ visitorResolveBatchV1: {
3112
+ parameters: {
3113
+ query?: never;
3114
+ header?: never;
3115
+ path?: never;
3116
+ cookie?: never;
3117
+ };
3118
+ requestBody?: never;
3119
+ responses: {
3120
+ /** @description crawlcheck-visitor with results[] */
3121
+ 200: {
3122
+ headers: {
3123
+ [name: string]: unknown;
3124
+ };
3125
+ content: {
3126
+ "application/json": unknown;
3127
+ };
3128
+ };
3129
+ };
3130
+ };
3131
+ conductV1: {
3132
+ parameters: {
3133
+ query?: never;
3134
+ header?: never;
3135
+ path?: never;
3136
+ cookie?: never;
3137
+ };
3138
+ requestBody?: never;
3139
+ responses: {
3140
+ /** @description crawlcheck-conduct */
3141
+ 200: {
3142
+ headers: {
3143
+ [name: string]: unknown;
3144
+ };
3145
+ content: {
3146
+ "application/json": unknown;
3147
+ };
3148
+ };
3149
+ };
3150
+ };
3151
+ conductAgentV1: {
3152
+ parameters: {
3153
+ query?: never;
3154
+ header?: never;
3155
+ path: {
3156
+ agent: string;
3157
+ };
3158
+ cookie?: never;
3159
+ };
3160
+ requestBody?: never;
3161
+ responses: {
3162
+ /** @description crawlcheck-conduct with one agent */
3163
+ 200: {
3164
+ headers: {
3165
+ [name: string]: unknown;
3166
+ };
3167
+ content: {
3168
+ "application/json": unknown;
3169
+ };
3170
+ };
3171
+ /** @description not observed, or not verifiable */
3172
+ 404: {
3173
+ headers: {
3174
+ [name: string]: unknown;
3175
+ };
3176
+ content?: never;
3177
+ };
3178
+ };
3179
+ };
3180
+ mcpLockUrl: {
3181
+ parameters: {
3182
+ query: {
3183
+ url: string;
1899
3184
  };
1900
- links?: Record<string, never>;
3185
+ header?: never;
3186
+ path?: never;
3187
+ cookie?: never;
1901
3188
  };
1902
- /** @description One observation in one shape (GET /api/v1/machine-record, MCP machine_record): subject, observation, findings (top in full without a licence; the rest locked), capabilities with safety class and verification state, evidence roots and verifier links */
1903
- MachineRecordV1: {
1904
- /** @constant */
1905
- kind: "crawlcheck-machine-record";
1906
- version: string;
1907
- subject: Record<string, never>;
1908
- observation: Record<string, never>;
1909
- /** @description each open finding carries trust {freshness, confidence {level, means, basis[]}, contradictions[]} */
1910
- findings: unknown[];
1911
- /** @description observed_at, age_hours, latest_report_id, is_latest, newer_scan_exists, last_second_reading_at */
1912
- freshness?: Record<string, never>;
1913
- /** @description With a licence: one line per fix that would change this record, best first (findings and rows it clears, other fixes some rows also need, score and letter after, root causes closed, certificate criteria flipped). Without: {fixes_available, best_single_fix {letter_after, score_after, findings_cleared, rows_cleared}} and no names */
1914
- fix_impact?: unknown[] | Record<string, never> | null;
1915
- /** @description score, letter, cap and the points each failing row moves (rows open with a licence); each open finding carries score_effect {points: 0, cap, binding, letter_without_it, says} */
1916
- score_ledger?: Record<string, never> | null;
1917
- /** @description counts and ratios plus vantages; no composite number; levels: contested | cross_vantage_confirmed | reproduced | single_reading */
1918
- confidence?: Record<string, never>;
1919
- /** @description site (the site contradicts itself) and between_networks_open (observers disagree), for findings this caller can open */
1920
- contradictions?: Record<string, never>;
1921
- findings_summary?: Record<string, never> | null;
1922
- findings_withheld?: string | null;
1923
- capabilities: Record<string, never>;
1924
- evidence: Record<string, never>;
1925
- access: Record<string, never>;
3189
+ requestBody?: never;
3190
+ responses: {
3191
+ /** @description crawlcheck-mcp-lock */
3192
+ 200: {
3193
+ headers: {
3194
+ [name: string]: unknown;
3195
+ };
3196
+ content: {
3197
+ "application/json": unknown;
3198
+ };
3199
+ };
3200
+ /** @description no tool list returned */
3201
+ 422: {
3202
+ headers: {
3203
+ [name: string]: unknown;
3204
+ };
3205
+ content?: never;
3206
+ };
1926
3207
  };
1927
- ErrorV1: {
1928
- error: {
1929
- code: string;
1930
- status?: number;
1931
- message: string;
3208
+ };
3209
+ mcpLockTools: {
3210
+ parameters: {
3211
+ query?: never;
3212
+ header?: never;
3213
+ path?: never;
3214
+ cookie?: never;
3215
+ };
3216
+ requestBody: {
3217
+ content: {
3218
+ "application/json": Record<string, never>;
1932
3219
  };
1933
3220
  };
1934
- /** @description GET /api/bundle: one file that checks offline with /crawlcheck-verify.mjs. A field that cannot be filled (an anonymous download, an unsealed day, a record from before manifests) is null with a *_withheld / *_missing / why reason, never omitted */
1935
- EvidenceBundleV1: {
1936
- /** @constant */
1937
- kind: "crawlcheck-evidence-bundle";
1938
- version: number;
1939
- generated_at?: string;
1940
- report: {
1941
- id: string | null;
1942
- domain: string | null;
1943
- path?: string | null;
1944
- scanned_at: string | null;
1945
- score_version?: number | null;
1946
- archived?: boolean;
3221
+ responses: {
3222
+ /** @description crawlcheck-mcp-lock */
3223
+ 200: {
3224
+ headers: {
3225
+ [name: string]: unknown;
3226
+ };
3227
+ content: {
3228
+ "application/json": unknown;
3229
+ };
1947
3230
  };
1948
- verifier: {
3231
+ };
3232
+ };
3233
+ mcpLockCheck: {
3234
+ parameters: {
3235
+ query?: never;
3236
+ header?: never;
3237
+ path?: never;
3238
+ cookie?: never;
3239
+ };
3240
+ requestBody: {
3241
+ content: {
3242
+ "application/json": Record<string, never>;
3243
+ };
3244
+ };
3245
+ responses: {
3246
+ /** @description crawlcheck-mcp-lock-check */
3247
+ 200: {
3248
+ headers: {
3249
+ [name: string]: unknown;
3250
+ };
3251
+ content: {
3252
+ "application/json": unknown;
3253
+ };
3254
+ };
3255
+ /** @description no lockfile */
3256
+ 400: {
3257
+ headers: {
3258
+ [name: string]: unknown;
3259
+ };
3260
+ content?: never;
3261
+ };
3262
+ };
3263
+ };
3264
+ mcpScanUrl: {
3265
+ parameters: {
3266
+ query: {
1949
3267
  url: string;
1950
- sha256: string;
1951
- run?: string;
1952
- page?: string;
1953
3268
  };
1954
- proves?: string[];
1955
- does_not_prove?: string[];
1956
- manifest: {
1957
- sha256: string;
1958
- body: string | null;
1959
- body_missing?: string | null;
1960
- signature?: {
1961
- alg?: string | null;
1962
- kid?: string | null;
1963
- message?: string | null;
1964
- sig?: string | null;
1965
- signed_at?: string | null;
1966
- } | null;
1967
- key?: {
1968
- jwk?: {
1969
- /** @constant */
1970
- kty: "OKP";
1971
- /** @constant */
1972
- crv: "Ed25519";
1973
- x: string;
1974
- };
1975
- kid?: string;
1976
- published_in?: string;
1977
- } | null;
1978
- key_missing?: string | null;
1979
- } | null;
1980
- record: {
1981
- digest: string | null;
1982
- subject: string | null;
1983
- subject_withheld?: string | null;
1984
- recipe?: string | null;
1985
- decision_leaves?: Record<string, never>[] | null;
1986
- lineage_leaves?: Record<string, never>[] | null;
1987
- leaves_withheld?: string | null;
1988
- } | null;
1989
- seal: {
1990
- /** @enum {unknown} */
1991
- state: "sealed" | "pending" | "unsealed" | "unverifiable" | "unknown";
1992
- day?: string | null;
1993
- root?: string | null;
1994
- path?: {
1995
- /** @enum {unknown} */
1996
- side: "left" | "right";
1997
- hash: string;
1998
- }[];
1999
- leaves_that_day?: number | null;
2000
- sealed_at?: string | null;
2001
- calendars?: string[];
2002
- ots_base64?: string | null;
2003
- bitcoin_block?: number | null;
2004
- recipe?: string | null;
2005
- why?: string | null;
2006
- } | null;
2007
- /** @description sec8: every bundle is scanned before it is served; a section that matched is null and carries <section>_withheld */
2008
- publish_guard?: {
2009
- checked?: string[];
2010
- withheld?: {
2011
- section?: string;
2012
- matched?: string[];
2013
- }[];
3269
+ header?: never;
3270
+ path?: never;
3271
+ cookie?: never;
3272
+ };
3273
+ requestBody?: never;
3274
+ responses: {
3275
+ /** @description crawlcheck-mcp-scan */
3276
+ 200: {
3277
+ headers: {
3278
+ [name: string]: unknown;
3279
+ };
3280
+ content: {
3281
+ "application/json": unknown;
3282
+ };
3283
+ };
3284
+ /** @description read limit */
3285
+ 429: {
3286
+ headers: {
3287
+ [name: string]: unknown;
3288
+ };
3289
+ content?: never;
2014
3290
  };
2015
- /** @description Who can read which representation of a scan: /docs/api#disclosure */
2016
- disclosure?: string;
2017
- } & {
2018
- [key: string]: string;
2019
3291
  };
2020
- /** @description A signed remediation receipt (GET /api/receipt?id=). receipt_id = rc1: + sha256 of the canonical JSON of every field except receipt_id and signature; signature = Ed25519 over 'crawlcheck-receipt-v1\n' + that sha256 */
2021
- RemediationReceiptV1: {
2022
- receipt_id: string;
2023
- /** @constant */
2024
- kind: "crawlcheck-remediation-receipt";
2025
- /** @constant */
2026
- v: 1;
2027
- issued_at: string;
2028
- issuer: {
2029
- observer?: string | null;
2030
- version_id?: string | null;
2031
- version_tag?: string | null;
2032
- key: {
2033
- kid: string;
2034
- jwk: Record<string, never>;
2035
- published_in?: string | null;
3292
+ };
3293
+ mcpScanTools: {
3294
+ parameters: {
3295
+ query?: never;
3296
+ header?: never;
3297
+ path?: never;
3298
+ cookie?: never;
3299
+ };
3300
+ requestBody: {
3301
+ content: {
3302
+ "application/json": Record<string, never>;
3303
+ };
3304
+ };
3305
+ responses: {
3306
+ /** @description crawlcheck-mcp-scan */
3307
+ 200: {
3308
+ headers: {
3309
+ [name: string]: unknown;
3310
+ };
3311
+ content: {
3312
+ "application/json": unknown;
3313
+ };
3314
+ };
3315
+ /** @description neither tools nor url */
3316
+ 400: {
3317
+ headers: {
3318
+ [name: string]: unknown;
3319
+ };
3320
+ content?: never;
3321
+ };
3322
+ };
3323
+ };
3324
+ rightsFeedIndex: {
3325
+ parameters: {
3326
+ query?: never;
3327
+ header?: never;
3328
+ path?: never;
3329
+ cookie?: never;
3330
+ };
3331
+ requestBody?: never;
3332
+ responses: {
3333
+ /** @description crawlcheck-rights-feed-index */
3334
+ 200: {
3335
+ headers: {
3336
+ [name: string]: unknown;
3337
+ };
3338
+ content: {
3339
+ "application/json": unknown;
2036
3340
  };
2037
3341
  };
2038
- subject: {
2039
- domain: string;
2040
- };
2041
- before: components["schemas"]["ReceiptSideV1"];
2042
- after: components["schemas"]["ReceiptSideV1"];
2043
- declared_fix: {
2044
- kind?: string;
2045
- declared_by?: string | null;
2046
- declared_at?: string | null;
2047
- plugin_version?: string | null;
2048
- fixes?: string[] | null;
2049
- note?: string | null;
2050
- };
2051
- deployed: {
2052
- at?: string | null;
2053
- basis?: string | null;
3342
+ };
3343
+ };
3344
+ rightsFeedFile: {
3345
+ parameters: {
3346
+ query?: never;
3347
+ header?: never;
3348
+ path: {
3349
+ id: string;
3350
+ file: string;
2054
3351
  };
2055
- verification: {
2056
- /** @enum {unknown} */
2057
- verdict: "improved" | "unchanged" | "mixed" | "regressed";
2058
- summary?: string | null;
2059
- comparable?: boolean;
2060
- findings?: Record<string, never>;
2061
- rows?: Record<string, never>;
2062
- files?: {
2063
- path?: string;
2064
- state?: string;
2065
- before_sha256?: string | null;
2066
- after_sha256?: string | null;
2067
- before_status?: number | null;
2068
- after_status?: number | null;
2069
- }[];
2070
- rollback_needed?: boolean;
2071
- rollback_steps?: Record<string, never>[];
2072
- method?: string | null;
3352
+ cookie?: never;
3353
+ };
3354
+ requestBody?: never;
3355
+ responses: {
3356
+ /** @description manifest or gzip part */
3357
+ 200: {
3358
+ headers: {
3359
+ [name: string]: unknown;
3360
+ };
3361
+ content: {
3362
+ "application/gzip": unknown;
3363
+ };
2073
3364
  };
2074
- links?: Record<string, never>;
2075
- signature: {
2076
- v?: number | null;
2077
- /** @constant */
2078
- alg: "Ed25519";
2079
- kid: string;
2080
- over?: string | null;
2081
- receipt_sha256: string;
2082
- message: string;
2083
- sig: string;
2084
- signed_at?: string | null;
2085
- canonical?: string | null;
3365
+ /** @description no such edition or file */
3366
+ 404: {
3367
+ headers: {
3368
+ [name: string]: unknown;
3369
+ };
3370
+ content?: never;
2086
3371
  };
2087
3372
  };
2088
- /** @description tr1: one scan's trace (GET /api/trace?id=, owner; sampled by the trace CI job). W3C Trace Context ids. Every span's parent is the scan span (root_span_id) or a span of this trace; the scan span's own parent is the caller's span when the scan joined a caller's trace (parent). */
2089
- TraceV1: {
2090
- id: string | null;
2091
- domain?: string | null;
2092
- scanned_at?: string | null;
2093
- traced: boolean;
2094
- why?: string | null;
2095
- trace_id?: string;
2096
- root_span_id?: string;
2097
- traceparent?: string;
2098
- parent?: {
2099
- span_id?: string;
2100
- source?: string | null;
2101
- previous_trace_id?: string | null;
2102
- } | null;
2103
- scan_id?: string | null;
2104
- started_at?: string | null;
2105
- total_ms?: number | null;
2106
- dropped?: number;
2107
- recorded_through?: unknown;
2108
- spans?: components["schemas"]["SpanV1"][];
2109
- errors?: {
2110
- error_id?: string | null;
2111
- stage?: string | null;
2112
- span_id: string | null;
2113
- error?: string | null;
2114
- }[];
2115
- findings?: {
2116
- code?: string | null;
2117
- decision_id?: string | null;
2118
- span_id?: string | null;
2119
- parent_span_id?: string | null;
2120
- parent_stage?: string | null;
2121
- reads?: number | null;
2122
- }[];
2123
- coverage?: Record<string, never>;
2124
- slowest?: unknown[];
2125
- decisions_with_spans?: number | null;
2126
- note?: string | null;
2127
- } & unknown;
2128
- /** @description tr1: one span: a stage of the scan, or (kind rule) one decision, started when its rule decided. */
2129
- SpanV1: {
2130
- span_id: string;
2131
- parent_span_id: string;
2132
- stage: string;
2133
- /** @enum {unknown} */
2134
- kind?: "rule";
2135
- start_ms: number;
2136
- dur_ms?: number | null;
2137
- /** @enum {unknown} */
2138
- status: "ok" | "error" | "inputs_disputed";
2139
- error_id?: string | null;
2140
- code?: string | null;
2141
- path?: string | null;
2142
- decision_id?: string | null;
2143
- reads?: {
2144
- experience_id?: string | null;
2145
- fetched_in?: string | null;
2146
- stage?: string | null;
2147
- fetched_after_rule?: boolean;
2148
- }[];
2149
- parent_basis?: string | null;
3373
+ };
3374
+ rightsV1: {
3375
+ parameters: {
3376
+ query: {
3377
+ domain: string;
3378
+ path?: string;
3379
+ agent?: string;
3380
+ };
3381
+ header?: never;
3382
+ path?: never;
3383
+ cookie?: never;
2150
3384
  };
2151
- /** @description dsp1: a signed resolution of a dispute against one finding (GET /api/disputes/resolution?id=). Verifies offline with crawlcheck-verify.mjs: hash, key id, Ed25519 signature, and the verdict re-derived from the recorded readings by the published decision table. */
2152
- DisputeResolutionV1: {
2153
- resolution_id: string;
2154
- /** @constant */
2155
- kind: "crawlcheck-dispute-resolution";
2156
- /** @constant */
2157
- v: 1;
2158
- schema?: string | null;
2159
- dispute_id: string;
2160
- issued_at: string;
2161
- issuer: {
2162
- observer?: string | null;
2163
- version_id?: string | null;
2164
- version_tag?: string | null;
2165
- key?: {
2166
- kid?: string;
2167
- jwk?: Record<string, never>;
2168
- published_in?: string;
3385
+ requestBody?: never;
3386
+ responses: {
3387
+ /** @description crawlcheck-rights */
3388
+ 200: {
3389
+ headers: {
3390
+ [name: string]: unknown;
2169
3391
  };
2170
- };
2171
- subject: {
2172
- domain: string;
2173
- record: Record<string, never>;
2174
- finding: {
2175
- code?: string;
2176
- path?: string | null;
2177
- fid?: string | null;
2178
- decision_id?: string | null;
2179
- title?: string | null;
2180
- severity?: number | null;
2181
- rule_revision?: number | null;
3392
+ content: {
3393
+ "application/json": unknown;
2182
3394
  };
2183
3395
  };
2184
- dispute: {
2185
- filed_at?: string;
2186
- /** @enum {unknown} */
2187
- ground?: "misread" | "fixed" | "network" | "rule";
2188
- ground_text?: string | null;
2189
- statement?: string;
2190
- ownership?: {
2191
- method?: string;
2192
- at?: string;
2193
- url?: string | null;
2194
- sha256?: string | null;
2195
- } | null;
2196
- };
2197
- remeasurement: {
2198
- replay: {
2199
- reproduces?: boolean | null;
2200
- rule?: string | null;
2201
- read?: unknown;
2202
- why?: string | null;
2203
- rule_revision?: number | null;
2204
- over?: string | null;
3396
+ /** @description not a public domain */
3397
+ 400: {
3398
+ headers: {
3399
+ [name: string]: unknown;
2205
3400
  };
2206
- observers: {
2207
- /** @enum {unknown} */
2208
- role: "primary" | "independent";
2209
- observer_id: string;
2210
- network_class?: string | null;
2211
- network?: string | null;
2212
- at?: string | null;
2213
- finding_present: boolean | null;
2214
- inputs_agree?: boolean | null;
2215
- method?: string | null;
2216
- reading?: string | null;
2217
- side?: Record<string, never> | null;
2218
- observation?: Record<string, never> | null;
2219
- }[];
2220
- deadline?: string | null;
2221
- independent_wait_hours?: number | null;
3401
+ content?: never;
2222
3402
  };
2223
- decision: {
2224
- /** @enum {unknown} */
2225
- verdict: "upheld" | "corrected" | "fixed_since" | "vantage_dependent" | "no_longer_observed" | "inconclusive";
2226
- verdict_text?: string | null;
2227
- /** @enum {unknown} */
2228
- effect: "stands" | "withdrawn" | "stands_for_record" | "stands_with_scope" | "stands_unresolved";
2229
- effect_text?: string | null;
2230
- rule?: string | null;
2231
- table?: string | null;
2232
- derived_by?: string | null;
3403
+ /** @description the site could not be read */
3404
+ 422: {
3405
+ headers: {
3406
+ [name: string]: unknown;
3407
+ };
3408
+ content?: never;
2233
3409
  };
2234
- links?: Record<string, never>;
2235
- signature: {
2236
- /** @constant */
2237
- v?: 1;
2238
- /** @constant */
2239
- alg: "Ed25519";
2240
- kid: string;
2241
- /** @constant */
2242
- over?: "resolution_sha256";
2243
- resolution_sha256: string;
2244
- message: string;
2245
- sig: string;
2246
- signed_at?: string;
2247
- canonical?: string;
3410
+ /** @description read limit */
3411
+ 429: {
3412
+ headers: {
3413
+ [name: string]: unknown;
3414
+ };
3415
+ content?: never;
2248
3416
  };
2249
3417
  };
2250
- /** @description Every finding the scanner can raise (GET /api/rules): what it means, its level, its fix and its share of counted scans. */
2251
- RulebookV1: {
2252
- ok?: boolean;
2253
- /** @constant */
2254
- kind: "crawlcheck-rulebook";
2255
- /** @constant */
2256
- v: 1;
2257
- generated_at: string;
2258
- score_version?: number | null;
2259
- schema?: string | null;
2260
- counts: {
2261
- rules: number;
2262
- by_kind?: {
2263
- [key: string]: number;
3418
+ };
3419
+ readEquivalenceV1: {
3420
+ parameters: {
3421
+ query: {
3422
+ url: string;
3423
+ };
3424
+ header?: never;
3425
+ path?: never;
3426
+ cookie?: never;
3427
+ };
3428
+ requestBody?: never;
3429
+ responses: {
3430
+ /** @description crawlcheck-read-equivalence */
3431
+ 200: {
3432
+ headers: {
3433
+ [name: string]: unknown;
2264
3434
  };
2265
- by_family?: {
2266
- [key: string]: number;
3435
+ content: {
3436
+ "application/json": unknown;
2267
3437
  };
2268
- revised?: number;
2269
- scored?: number;
2270
3438
  };
2271
- scans_counted?: number | null;
2272
- severity_scale: {
2273
- level?: string;
2274
- }[];
2275
- method?: {
2276
- revisions?: string | null;
2277
- share?: string | null;
2278
- grade?: string | null;
3439
+ /** @description not a public http(s) URL */
3440
+ 400: {
3441
+ headers: {
3442
+ [name: string]: unknown;
3443
+ };
3444
+ content?: never;
3445
+ };
3446
+ /** @description read limit */
3447
+ 429: {
3448
+ headers: {
3449
+ [name: string]: unknown;
3450
+ };
3451
+ content?: never;
2279
3452
  };
2280
- /** @description every rule; with ?code= only that rule (counts still describe the whole rulebook) */
2281
- rules: components["schemas"]["RuleV1"][];
2282
- filter?: {
2283
- code?: string | null;
2284
- } | null;
2285
3453
  };
2286
- /** @description One rule: the code, what it means, its level, its current revision, its fix and its share of counted scans. */
2287
- RuleV1: {
2288
- code: string;
2289
- /**
2290
- * @description self_audit: a defect in CrawlCheck's own record, never in the site
2291
- * @enum {unknown}
2292
- */
2293
- kind: "scan" | "answer_correlation" | "capability_mismatch" | "self_audit";
2294
- family: {
2295
- id: string;
2296
- label: string;
3454
+ };
3455
+ selfClaimsV1: {
3456
+ parameters: {
3457
+ query: {
3458
+ domain: string;
2297
3459
  };
2298
- title: string | null;
2299
- meaning?: string | null;
2300
- severity: {
2301
- level?: string | null;
3460
+ header?: never;
3461
+ path?: never;
3462
+ cookie?: never;
3463
+ };
3464
+ requestBody?: never;
3465
+ responses: {
3466
+ /** @description crawlcheck-claims */
3467
+ 200: {
3468
+ headers: {
3469
+ [name: string]: unknown;
3470
+ };
3471
+ content: {
3472
+ "application/json": unknown;
3473
+ };
2302
3474
  };
2303
- /** @description raised on a graded scan record; refusals, answer runs, capability mismatches and self-audit findings are not */
2304
- scored?: boolean;
2305
- measured_on?: string | null;
2306
- revision: {
2307
- current: number;
2308
- /** @description when the current revision took effect; null while the rule is at revision 1 */
2309
- revised_at?: string | null;
3475
+ /** @description not a public domain */
3476
+ 400: {
3477
+ headers: {
3478
+ [name: string]: unknown;
3479
+ };
3480
+ content?: never;
2310
3481
  };
2311
- fix?: {
2312
- advice?: string | null;
2313
- effort?: string | null;
2314
- endpoint?: string | null;
3482
+ /** @description the site could not be read */
3483
+ 422: {
3484
+ headers: {
3485
+ [name: string]: unknown;
3486
+ };
3487
+ content?: never;
2315
3488
  };
2316
- share_of_scans: {
2317
- pct: number | null;
2318
- scans?: number | null;
2319
- of_scans?: number | null;
2320
- basis: string;
3489
+ /** @description read limit */
3490
+ 429: {
3491
+ headers: {
3492
+ [name: string]: unknown;
3493
+ };
3494
+ content?: never;
2321
3495
  };
2322
- links?: {
2323
- self?: string | null;
2324
- api?: string | null;
2325
- glossary?: string[];
2326
- workflow?: string | null;
2327
- lineage?: string | null;
2328
- explain_template?: string | null;
3496
+ };
3497
+ };
3498
+ originByAnchorV1: {
3499
+ parameters: {
3500
+ query: {
3501
+ passage: string;
2329
3502
  };
3503
+ header?: never;
3504
+ path?: never;
3505
+ cookie?: never;
2330
3506
  };
2331
- /** @description What the owner's connected outcome sources counted either side of a receipt's anchor day (GET /api/outcomes). One series per named source; per-day values compared; a series with no source is connected:false with how_to_connect; a window under 7 measured days is usable:false with why. Never a claim of cause. */
2332
- FixOutcomesV1: {
2333
- ok?: boolean;
2334
- /** @constant */
2335
- kind: "crawlcheck-fix-outcomes";
2336
- /** @constant */
2337
- v: 1;
2338
- generated_at?: string;
2339
- cached?: boolean;
2340
- receipt: {
2341
- id: string;
2342
- domain: string;
2343
- verdict?: string | null;
2344
- findings_cleared?: string[];
2345
- url?: string;
2346
- anchor: {
2347
- at?: string;
2348
- /** Format: date */
2349
- day: string;
2350
- basis: string;
3507
+ requestBody?: never;
3508
+ responses: {
3509
+ /** @description crawlcheck-origin */
3510
+ 200: {
3511
+ headers: {
3512
+ [name: string]: unknown;
3513
+ };
3514
+ content: {
3515
+ "application/json": unknown;
2351
3516
  };
2352
3517
  };
2353
- window: {
2354
- days: number;
2355
- before: {
2356
- from?: string | null;
2357
- to?: string | null;
3518
+ };
3519
+ };
3520
+ originV1: {
3521
+ parameters: {
3522
+ query?: never;
3523
+ header?: never;
3524
+ path?: never;
3525
+ cookie?: never;
3526
+ };
3527
+ requestBody?: never;
3528
+ responses: {
3529
+ /** @description crawlcheck-origin */
3530
+ 200: {
3531
+ headers: {
3532
+ [name: string]: unknown;
2358
3533
  };
2359
- after: {
2360
- from?: string | null;
2361
- to?: string | null;
2362
- days_elapsed?: number;
2363
- complete?: boolean;
3534
+ content: {
3535
+ "application/json": unknown;
2364
3536
  };
2365
3537
  };
2366
- connected: number;
2367
- usable: number;
2368
- series: {
2369
- key: string;
2370
- label: string;
2371
- source: string;
2372
- /** @enum {unknown} */
2373
- mode: "daily" | "events";
2374
- connected: boolean;
2375
- note?: string;
2376
- how_to_connect?: string | null;
2377
- before?: components["schemas"]["OutcomeSideV1"] | null;
2378
- after?: components["schemas"]["OutcomeSideV1"] | null;
2379
- delta_per_day?: number | null;
2380
- pct?: number | null;
2381
- usable: boolean;
2382
- why: string;
2383
- }[];
2384
- not_measured?: {
2385
- key?: string;
2386
- why?: string;
2387
- }[];
2388
- summary?: string;
2389
- reading?: string;
2390
- not_proof: string;
2391
- how_to_cite?: string;
2392
3538
  };
2393
- OutcomeSideV1: {
2394
- from?: string | null;
2395
- to?: string | null;
2396
- days: number;
2397
- measured: number;
2398
- sum: number;
2399
- per_day: number | null;
3539
+ };
3540
+ contentClockV1: {
3541
+ parameters: {
3542
+ query: {
3543
+ url: string;
3544
+ };
3545
+ header?: never;
3546
+ path?: never;
3547
+ cookie?: never;
2400
3548
  };
2401
- ReceiptSideV1: {
2402
- report_id: string | null;
2403
- scanned_at: string | null;
2404
- grade?: string | null;
2405
- score?: number | null;
2406
- score_version?: number | null;
2407
- refused?: boolean;
2408
- findings?: number | null;
2409
- manifest_sha256?: string | null;
2410
- decision_root?: string | null;
2411
- trace_id?: string | null;
3549
+ requestBody?: never;
3550
+ responses: {
3551
+ /** @description crawlcheck-content-clock */
3552
+ 200: {
3553
+ headers: {
3554
+ [name: string]: unknown;
3555
+ };
3556
+ content: {
3557
+ "application/json": unknown;
3558
+ };
3559
+ };
3560
+ /** @description page unreadable */
3561
+ 422: {
3562
+ headers: {
3563
+ [name: string]: unknown;
3564
+ };
3565
+ content?: never;
3566
+ };
2412
3567
  };
2413
3568
  };
2414
- responses: never;
2415
- parameters: never;
2416
- requestBodies: never;
2417
- headers: never;
2418
- pathItems: never;
2419
- }
2420
- export type $defs = Record<string, never>;
2421
- export interface operations {
2422
- scan: {
3569
+ citedByV1: {
2423
3570
  parameters: {
2424
- query?: never;
3571
+ query?: {
3572
+ url?: string;
3573
+ domain?: string;
3574
+ };
2425
3575
  header?: never;
2426
3576
  path?: never;
2427
3577
  cookie?: never;
2428
3578
  };
2429
- requestBody: {
2430
- content: {
2431
- "application/json": {
2432
- /**
2433
- * @description A bare domain or a full URL
2434
- * @example example.com
2435
- */
2436
- domain: string;
2437
- /**
2438
- * @description unlisted: the report is reachable only by its link; the scan is sealed and archived but enters no public registry, dataset, history or resolve answer. private: needs a licence for the domain (or the owner); the report opens only for that licence holder or the owner and is not archived or listed anywhere (default public)
2439
- * @enum {unknown}
2440
- */
2441
- visibility?: "public" | "unlisted" | "private";
2442
- };
2443
- };
2444
- };
3579
+ requestBody?: never;
2445
3580
  responses: {
2446
- /** @description The scan record */
3581
+ /** @description crawlcheck-cited-by */
2447
3582
  200: {
2448
3583
  headers: {
2449
3584
  [name: string]: unknown;
2450
3585
  };
2451
3586
  content: {
2452
- "application/json": components["schemas"]["ScanRecord"];
3587
+ "application/json": unknown;
2453
3588
  };
2454
3589
  };
2455
- /** @description Not a public domain (reserved names such as .example and .invalid included), or no JSON body */
3590
+ /** @description give url or domain */
2456
3591
  400: {
2457
3592
  headers: {
2458
3593
  [name: string]: unknown;
2459
3594
  };
2460
3595
  content?: never;
2461
3596
  };
2462
- /** @description Rate limited: 5 requests per 10 seconds per address; a scan of the same domain still running (code scan_in_progress); or the daily total of free scans reached (code daily_budget). Retry-After says when. A rescan of a domain scanned in the last 2 minutes returns that report (field cached) instead of fetching the site again; a domain where nothing answered returns 200 with unreachable: true, id: null and nothing stored */
2463
- 429: {
3597
+ };
3598
+ };
3599
+ anchorCreateV1: {
3600
+ parameters: {
3601
+ query?: never;
3602
+ header?: never;
3603
+ path?: never;
3604
+ cookie?: never;
3605
+ };
3606
+ requestBody?: never;
3607
+ responses: {
3608
+ /** @description crawlcheck-anchor */
3609
+ 201: {
3610
+ headers: {
3611
+ [name: string]: unknown;
3612
+ };
3613
+ content: {
3614
+ "application/json": unknown;
3615
+ };
3616
+ };
3617
+ /** @description page unreachable or passage not found */
3618
+ 422: {
2464
3619
  headers: {
2465
3620
  [name: string]: unknown;
2466
3621
  };
2467
3622
  content?: never;
2468
3623
  };
2469
- /** @description Free scans paused (code scans_paused); keyed scans are unaffected */
2470
- 503: {
3624
+ };
3625
+ };
3626
+ anchorWatchV1: {
3627
+ parameters: {
3628
+ query?: never;
3629
+ header?: never;
3630
+ path: {
3631
+ id: string;
3632
+ };
3633
+ cookie?: never;
3634
+ };
3635
+ requestBody?: never;
3636
+ responses: {
3637
+ /** @description watching */
3638
+ 200: {
3639
+ headers: {
3640
+ [name: string]: unknown;
3641
+ };
3642
+ content: {
3643
+ "application/json": unknown;
3644
+ };
3645
+ };
3646
+ /** @description no such anchor */
3647
+ 404: {
2471
3648
  headers: {
2472
3649
  [name: string]: unknown;
2473
3650
  };
@@ -2475,39 +3652,83 @@ export interface operations {
2475
3652
  };
2476
3653
  };
2477
3654
  };
2478
- scanDomainV1: {
3655
+ anchorSinkV1: {
2479
3656
  parameters: {
2480
3657
  query?: never;
2481
3658
  header?: never;
2482
- path?: never;
3659
+ path: {
3660
+ token: string;
3661
+ };
2483
3662
  cookie?: never;
2484
3663
  };
2485
- requestBody: {
2486
- content: {
2487
- "application/json": {
2488
- domain: string;
3664
+ requestBody?: never;
3665
+ responses: {
3666
+ /** @description deliveries */
3667
+ 200: {
3668
+ headers: {
3669
+ [name: string]: unknown;
2489
3670
  };
3671
+ content: {
3672
+ "application/json": unknown;
3673
+ };
3674
+ };
3675
+ };
3676
+ };
3677
+ anchorGetV1: {
3678
+ parameters: {
3679
+ query?: {
3680
+ recheck?: "1";
3681
+ };
3682
+ header?: never;
3683
+ path: {
3684
+ id: string;
2490
3685
  };
3686
+ cookie?: never;
2491
3687
  };
3688
+ requestBody?: never;
2492
3689
  responses: {
2493
- /** @description PublicReportV1 */
3690
+ /** @description anchor, seal, and check when asked */
2494
3691
  200: {
2495
3692
  headers: {
2496
3693
  [name: string]: unknown;
2497
3694
  };
2498
3695
  content: {
2499
- "application/json": components["schemas"]["PublicReportV1"];
3696
+ "application/json": unknown;
2500
3697
  };
2501
3698
  };
2502
- /** @description ErrorV1: bad_request */
2503
- 400: {
3699
+ /** @description no such anchor */
3700
+ 404: {
2504
3701
  headers: {
2505
3702
  [name: string]: unknown;
2506
3703
  };
2507
3704
  content?: never;
2508
3705
  };
2509
- /** @description ErrorV1: rate_limited */
2510
- 429: {
3706
+ };
3707
+ };
3708
+ visitorArrivalV1: {
3709
+ parameters: {
3710
+ query: {
3711
+ ua: string;
3712
+ path?: string;
3713
+ verdict?: "verified" | "spoofed" | "unverifiable";
3714
+ };
3715
+ header?: never;
3716
+ path?: never;
3717
+ cookie?: never;
3718
+ };
3719
+ requestBody?: never;
3720
+ responses: {
3721
+ /** @description recorded */
3722
+ 200: {
3723
+ headers: {
3724
+ [name: string]: unknown;
3725
+ };
3726
+ content: {
3727
+ "application/json": unknown;
3728
+ };
3729
+ };
3730
+ /** @description not a Worker subrequest */
3731
+ 403: {
2511
3732
  headers: {
2512
3733
  [name: string]: unknown;
2513
3734
  };
@@ -2515,7 +3736,7 @@ export interface operations {
2515
3736
  };
2516
3737
  };
2517
3738
  };
2518
- reportAgentOutcomeV1: {
3739
+ trafficIndexV1: {
2519
3740
  parameters: {
2520
3741
  query?: never;
2521
3742
  header?: never;
@@ -2524,8 +3745,8 @@ export interface operations {
2524
3745
  };
2525
3746
  requestBody?: never;
2526
3747
  responses: {
2527
- /** @description accepted */
2528
- 202: {
3748
+ /** @description crawlcheck-traffic-index */
3749
+ 200: {
2529
3750
  headers: {
2530
3751
  [name: string]: unknown;
2531
3752
  };
@@ -2533,15 +3754,30 @@ export interface operations {
2533
3754
  "application/json": unknown;
2534
3755
  };
2535
3756
  };
2536
- /** @description invalid report */
2537
- 400: {
3757
+ };
3758
+ };
3759
+ trafficIndexMonthV1: {
3760
+ parameters: {
3761
+ query?: never;
3762
+ header?: never;
3763
+ path: {
3764
+ month: string;
3765
+ };
3766
+ cookie?: never;
3767
+ };
3768
+ requestBody?: never;
3769
+ responses: {
3770
+ /** @description crawlcheck-traffic-index */
3771
+ 200: {
2538
3772
  headers: {
2539
3773
  [name: string]: unknown;
2540
3774
  };
2541
- content?: never;
3775
+ content: {
3776
+ "application/json": unknown;
3777
+ };
2542
3778
  };
2543
- /** @description 500 reports a day per address */
2544
- 429: {
3779
+ /** @description no such month */
3780
+ 404: {
2545
3781
  headers: {
2546
3782
  [name: string]: unknown;
2547
3783
  };
@@ -2549,18 +3785,16 @@ export interface operations {
2549
3785
  };
2550
3786
  };
2551
3787
  };
2552
- agentOutcomesV1: {
3788
+ visitorStatsV1: {
2553
3789
  parameters: {
2554
- query: {
2555
- domain: string;
2556
- };
3790
+ query?: never;
2557
3791
  header?: never;
2558
3792
  path?: never;
2559
3793
  cookie?: never;
2560
3794
  };
2561
3795
  requestBody?: never;
2562
3796
  responses: {
2563
- /** @description crawlcheck-agent-outcomes */
3797
+ /** @description crawlcheck-visitor-stats */
2564
3798
  200: {
2565
3799
  headers: {
2566
3800
  [name: string]: unknown;
@@ -2571,18 +3805,20 @@ export interface operations {
2571
3805
  };
2572
3806
  };
2573
3807
  };
2574
- aiAccuracyV1: {
3808
+ decisionCheckV1: {
2575
3809
  parameters: {
2576
- query: {
2577
- domain: string;
3810
+ query?: {
3811
+ host?: string;
2578
3812
  };
2579
3813
  header?: never;
2580
- path?: never;
3814
+ path: {
3815
+ sha256: string;
3816
+ };
2581
3817
  cookie?: never;
2582
3818
  };
2583
3819
  requestBody?: never;
2584
3820
  responses: {
2585
- /** @description crawlcheck-ai-accuracy */
3821
+ /** @description crawlcheck-decision-check */
2586
3822
  200: {
2587
3823
  headers: {
2588
3824
  [name: string]: unknown;
@@ -2591,7 +3827,7 @@ export interface operations {
2591
3827
  "application/json": unknown;
2592
3828
  };
2593
3829
  };
2594
- /** @description not tracked or not measured */
3830
+ /** @description no receipt with that digest is held */
2595
3831
  404: {
2596
3832
  headers: {
2597
3833
  [name: string]: unknown;
@@ -2600,18 +3836,95 @@ export interface operations {
2600
3836
  };
2601
3837
  };
2602
3838
  };
2603
- domainLifecycleV1: {
3839
+ decisionStatsV1: {
2604
3840
  parameters: {
2605
- query: {
2606
- domain: string;
3841
+ query?: never;
3842
+ header?: never;
3843
+ path?: never;
3844
+ cookie?: never;
3845
+ };
3846
+ requestBody?: never;
3847
+ responses: {
3848
+ /** @description crawlcheck-decision-stats */
3849
+ 200: {
3850
+ headers: {
3851
+ [name: string]: unknown;
3852
+ };
3853
+ content: {
3854
+ "application/json": unknown;
3855
+ };
3856
+ };
3857
+ };
3858
+ };
3859
+ resolvePrefixV1: {
3860
+ parameters: {
3861
+ query?: never;
3862
+ header?: never;
3863
+ path: {
3864
+ prefix: string;
3865
+ };
3866
+ cookie?: never;
3867
+ };
3868
+ requestBody?: never;
3869
+ responses: {
3870
+ /** @description crawlcheck-resolve-prefix */
3871
+ 200: {
3872
+ headers: {
3873
+ [name: string]: unknown;
3874
+ };
3875
+ content: {
3876
+ "application/json": unknown;
3877
+ };
3878
+ };
3879
+ /** @description more than 100 answers share the prefix; send a longer one */
3880
+ 413: {
3881
+ headers: {
3882
+ [name: string]: unknown;
3883
+ };
3884
+ content?: never;
3885
+ };
3886
+ /** @description the index is built when the first daily snapshot finishes */
3887
+ 503: {
3888
+ headers: {
3889
+ [name: string]: unknown;
3890
+ };
3891
+ content?: never;
2607
3892
  };
3893
+ };
3894
+ };
3895
+ resolveSnapshotIndex: {
3896
+ parameters: {
3897
+ query?: never;
2608
3898
  header?: never;
2609
3899
  path?: never;
2610
3900
  cookie?: never;
2611
3901
  };
2612
3902
  requestBody?: never;
2613
3903
  responses: {
2614
- /** @description crawlcheck-domain */
3904
+ /** @description crawlcheck-snapshot-index */
3905
+ 200: {
3906
+ headers: {
3907
+ [name: string]: unknown;
3908
+ };
3909
+ content: {
3910
+ "application/json": unknown;
3911
+ };
3912
+ };
3913
+ };
3914
+ };
3915
+ resolveSnapshotFile: {
3916
+ parameters: {
3917
+ query?: never;
3918
+ header?: never;
3919
+ path: {
3920
+ id: string;
3921
+ file: string;
3922
+ };
3923
+ cookie?: never;
3924
+ };
3925
+ requestBody?: never;
3926
+ responses: {
3927
+ /** @description manifest.json or a gzip part */
2615
3928
  200: {
2616
3929
  headers: {
2617
3930
  [name: string]: unknown;
@@ -2620,6 +3933,13 @@ export interface operations {
2620
3933
  "application/json": unknown;
2621
3934
  };
2622
3935
  };
3936
+ /** @description unknown or deleted snapshot file */
3937
+ 404: {
3938
+ headers: {
3939
+ [name: string]: unknown;
3940
+ };
3941
+ content?: never;
3942
+ };
2623
3943
  };
2624
3944
  };
2625
3945
  resolveChangesV1: {