[
  {
    "path": "/",
    "group": "Meta",
    "what": "index page linking every fixture",
    "sentinel": "MOCKSRV::index::OK"
  },
  {
    "path": "/health",
    "group": "Meta",
    "what": "liveness probe",
    "sentinel": "MOCKSRV::health::OK"
  },
  {
    "path": "/manifest.json",
    "group": "Meta",
    "what": "this catalogue, as JSON"
  },
  {
    "path": "/timeout?timeout=20",
    "group": "Timing",
    "what": "responds after N seconds",
    "sentinel": "MOCKSRV::timeout::OK"
  },
  {
    "path": "/drip?chunks=10&duration=5",
    "group": "Timing",
    "what": "body trickles over N seconds",
    "sentinel": "MOCKSRV::drip::OK"
  },
  {
    "path": "/hang",
    "group": "Timing",
    "what": "never responds (5min cap)",
    "indirect": true
  },
  {
    "path": "/reset",
    "group": "Timing",
    "what": "connection dies mid-body",
    "indirect": true
  },
  {
    "path": "/flaky/reset?key=a",
    "group": "Status codes",
    "what": "clears one key, or all when omitted"
  },
  {
    "path": "/status/404",
    "group": "Status codes",
    "what": "any status code",
    "sentinel": "MOCKSRV::status::OK",
    "indirect": true
  },
  {
    "path": "/flaky?key=a&fail=2&code=503",
    "group": "Status codes",
    "what": "fails N times per key, then 200",
    "sentinel": "MOCKSRV::flaky::OK",
    "indirect": true
  },
  {
    "path": "/redirect/3",
    "group": "Redirects",
    "what": "N-hop redirect chain"
  },
  {
    "path": "/redirect-to?url=/json",
    "group": "Redirects",
    "what": "single redirect to any URL"
  },
  {
    "path": "/redirect/loop",
    "group": "Redirects",
    "what": "infinite redirect loop"
  },
  {
    "path": "/meta-refresh?to=/html/article",
    "group": "Redirects",
    "what": "meta-refresh redirect"
  },
  {
    "path": "/redirect/preserve-307",
    "group": "Redirects",
    "what": "307 — method and body preserved"
  },
  {
    "path": "/redirect/preserve-308",
    "group": "Redirects",
    "what": "308 — method and body preserved"
  },
  {
    "path": "/redirect/relative",
    "group": "Redirects",
    "what": "Location without a leading slash"
  },
  {
    "path": "/redirect/offsite?to=https://example.com/",
    "group": "Redirects",
    "what": "Location on another origin"
  },
  {
    "path": "/redirect/cookie-hop",
    "group": "Redirects",
    "what": "resolves only once the cookie is echoed",
    "sentinel": "MOCKSRV::redirect-cookie-hop::OK",
    "indirect": true
  },
  {
    "path": "/html/iframe-child",
    "group": "HTML shapes",
    "what": "the frame /html/iframe embeds",
    "sentinel": "MOCKSRV::html-iframe::OK"
  },
  {
    "path": "/html/article",
    "group": "HTML shapes",
    "what": "clean article, og + ld+json",
    "sentinel": "MOCKSRV::html-article::OK"
  },
  {
    "path": "/html/malformed",
    "group": "HTML shapes",
    "what": "unclosed tags",
    "sentinel": "MOCKSRV::html-malformed::OK"
  },
  {
    "path": "/html/huge?kb=500",
    "group": "HTML shapes",
    "what": "large payload, sentinel at end",
    "sentinel": "MOCKSRV::html-huge::OK"
  },
  {
    "path": "/html/charset?declare=header",
    "group": "HTML shapes",
    "what": "ISO-8859-9 bytes",
    "sentinel": "MOCKSRV::html-charset::OK",
    "indirect": true
  },
  {
    "path": "/html/empty",
    "group": "HTML shapes",
    "what": "200 with empty body"
  },
  {
    "path": "/html/iframe",
    "group": "HTML shapes",
    "what": "content in a child frame",
    "sentinel": "MOCKSRV::html-iframe::OK",
    "indirect": true
  },
  {
    "path": "/html/noscript",
    "group": "HTML shapes",
    "what": "content only in <noscript>",
    "sentinel": "MOCKSRV::html-noscript::OK"
  },
  {
    "path": "/html/boilerplate",
    "group": "HTML shapes",
    "what": "article buried in nav/aside/footer noise",
    "sentinel": "MOCKSRV::html-boilerplate::OK"
  },
  {
    "path": "/html/rich",
    "group": "HTML shapes",
    "what": "tables, code, lists, images — markdown fidelity",
    "sentinel": "MOCKSRV::html-rich::OK"
  },
  {
    "path": "/html/unicode",
    "group": "HTML shapes",
    "what": "emoji, CJK, RTL, combining marks, BOM",
    "sentinel": "MOCKSRV::html-unicode::OK"
  },
  {
    "path": "/js/csr?delay=500",
    "group": "JS / CSR",
    "what": "CSR — JS writes content after N ms",
    "sentinel": "MOCKSRV::js-csr::OK",
    "renderOnly": true
  },
  {
    "path": "/js/fetch",
    "group": "JS / CSR",
    "what": "content via fetch() after load",
    "sentinel": "MOCKSRV::json::OK",
    "indirect": true
  },
  {
    "path": "/js/lazy",
    "group": "JS / CSR",
    "what": "IntersectionObserver, needs scroll",
    "sentinel": "MOCKSRV::js-lazy::OK",
    "renderOnly": true
  },
  {
    "path": "/js/infinite?pages=3",
    "group": "JS / CSR",
    "what": "infinite scroll, N pages",
    "sentinel": "MOCKSRV::js-infinite::OK",
    "renderOnly": true
  },
  {
    "path": "/js/shadow",
    "group": "JS / CSR",
    "what": "content inside a shadow root",
    "sentinel": "MOCKSRV::js-shadow::OK",
    "renderOnly": true
  },
  {
    "path": "/js/redirect?to=/json",
    "group": "JS / CSR",
    "what": "location.replace navigation"
  },
  {
    "path": "/js/hydrate",
    "group": "JS / CSR",
    "what": "SSR markup replaced on hydration",
    "sentinel": "MOCKSRV::js-hydrate::OK",
    "renderOnly": true
  },
  {
    "path": "/wall/cookie",
    "group": "Walls + cookies",
    "what": "consent overlay over content",
    "sentinel": "MOCKSRV::wall-cookie::OK"
  },
  {
    "path": "/wall/cookie-gate",
    "group": "Walls + cookies",
    "what": "403 unless cookie consent=1",
    "sentinel": "MOCKSRV::wall-cookie-gate::OK",
    "indirect": true
  },
  {
    "path": "/cookies/set?name=consent&value=1",
    "group": "Walls + cookies",
    "what": "sets a cookie",
    "sentinel": "MOCKSRV::cookies-set::OK"
  },
  {
    "path": "/wall/paywall",
    "group": "Walls + cookies",
    "what": "truncated article + paywall",
    "sentinel": "MOCKSRV::wall-paywall::OK"
  },
  {
    "path": "/wall/login",
    "group": "Walls + cookies",
    "what": "401 login form"
  },
  {
    "path": "/wall/captcha",
    "group": "Walls + cookies",
    "what": "403 captcha page"
  },
  {
    "path": "/wall/bot",
    "group": "Walls + cookies",
    "what": "403 unless UA looks like a browser",
    "sentinel": "MOCKSRV::wall-bot::OK",
    "indirect": true
  },
  {
    "path": "/auth/basic?user=user&pass=pass",
    "group": "Auth",
    "what": "HTTP basic auth",
    "sentinel": "MOCKSRV::auth-basic::OK",
    "indirect": true
  },
  {
    "path": "/auth/bearer?token=secret",
    "group": "Auth",
    "what": "bearer token auth",
    "sentinel": "MOCKSRV::auth-bearer::OK",
    "indirect": true
  },
  {
    "path": "/json",
    "group": "Content types",
    "what": "application/json",
    "sentinel": "MOCKSRV::json::OK"
  },
  {
    "path": "/xml",
    "group": "Content types",
    "what": "application/xml",
    "sentinel": "MOCKSRV::xml::OK"
  },
  {
    "path": "/csv",
    "group": "Content types",
    "what": "text/csv",
    "sentinel": "MOCKSRV::csv::OK"
  },
  {
    "path": "/text",
    "group": "Content types",
    "what": "text/plain",
    "sentinel": "MOCKSRV::text::OK"
  },
  {
    "path": "/pdf",
    "group": "Content types",
    "what": "application/pdf",
    "sentinel": "MOCKSRV::pdf::OK"
  },
  {
    "path": "/gzip",
    "group": "Content types",
    "what": "gzip-encoded html",
    "sentinel": "MOCKSRV::gzip::OK",
    "indirect": true
  },
  {
    "path": "/content-type?type=application/octet-stream",
    "group": "Content types",
    "what": "html served as any type",
    "sentinel": "MOCKSRV::content-type::OK"
  },
  {
    "path": "/bytes/1024",
    "group": "Content types",
    "what": "exact N bytes"
  },
  {
    "path": "/brotli",
    "group": "Content types",
    "what": "brotli-encoded html",
    "sentinel": "MOCKSRV::brotli::OK",
    "indirect": true
  },
  {
    "path": "/deflate",
    "group": "Content types",
    "what": "deflate-encoded html",
    "sentinel": "MOCKSRV::deflate::OK",
    "indirect": true
  },
  {
    "path": "/lie/gzip",
    "group": "Lying headers",
    "what": "declares gzip, sends plain text",
    "sentinel": "MOCKSRV::lie-gzip::OK",
    "indirect": true
  },
  {
    "path": "/lie/charset",
    "group": "Lying headers",
    "what": "declares utf-8, sends latin5",
    "sentinel": "MOCKSRV::lie-charset::OK",
    "indirect": true
  },
  {
    "path": "/lie/length",
    "group": "Lying headers",
    "what": "content-length >> body, then socket drop",
    "sentinel": "MOCKSRV::lie-length::OK",
    "indirect": true
  },
  {
    "path": "/cache/etag",
    "group": "Caching + rate limits",
    "what": "ETag, 304 on If-None-Match",
    "sentinel": "MOCKSRV::cache-etag::OK"
  },
  {
    "path": "/cache/last-modified",
    "group": "Caching + rate limits",
    "what": "Last-Modified, 304 on If-Modified-Since",
    "sentinel": "MOCKSRV::cache-last-modified::OK"
  },
  {
    "path": "/rate-limit",
    "group": "Caching + rate limits",
    "what": "429 + retry-after seconds + x-ratelimit-*",
    "indirect": true
  },
  {
    "path": "/rate-limit/date",
    "group": "Caching + rate limits",
    "what": "503 + retry-after as an HTTP-date",
    "indirect": true
  },
  {
    "path": "/robots.txt",
    "group": "Crawl surface",
    "what": "disallows /blocked/"
  },
  {
    "path": "/sitemap.xml?n=10",
    "group": "Crawl surface",
    "what": "N urls"
  },
  {
    "path": "/blocked/page",
    "group": "Crawl surface",
    "what": "robots-disallowed page",
    "sentinel": "MOCKSRV::blocked::OK"
  },
  {
    "path": "/links?n=20",
    "group": "Crawl surface",
    "what": "page with N internal links",
    "sentinel": "MOCKSRV::links::OK"
  },
  {
    "path": "/deep/1",
    "group": "Crawl surface",
    "what": "each level links to the next",
    "sentinel": "MOCKSRV::deep-1::OK"
  },
  {
    "path": "/crawl/page/1",
    "group": "Crawl surface",
    "what": "leaf page, sitemap target",
    "sentinel": "MOCKSRV::crawl-page::OK"
  },
  {
    "path": "/html/base-href",
    "group": "Crawl surface",
    "what": "<base href> rewrites relative links",
    "sentinel": "MOCKSRV::html-base-href::OK"
  },
  {
    "path": "/html/norobots",
    "group": "Crawl surface",
    "what": "meta robots noindex,nofollow + rel=nofollow",
    "sentinel": "MOCKSRV::html-norobots::OK"
  },
  {
    "path": "/html/canonical",
    "group": "Crawl surface",
    "what": "near-duplicate, canonical to /html/article",
    "sentinel": "MOCKSRV::html-canonical::OK"
  },
  {
    "path": "/html/paginated?page=1",
    "group": "Crawl surface",
    "what": "rel=next / rel=prev pagination",
    "sentinel": "MOCKSRV::html-paginated::OK"
  },
  {
    "path": "/headers",
    "group": "Diagnostics",
    "what": "echoes request headers",
    "sentinel": "MOCKSRV::headers::OK"
  },
  {
    "path": "/echo",
    "group": "Diagnostics",
    "what": "echoes method, headers, body",
    "sentinel": "MOCKSRV::echo::OK"
  }
]