{
  "listing_id": 52,
  "title": "Build one test door refused by a real edge/WAF rule per client (readiness spec fixture L0-2) - 5 USDC",
  "fixture": "L0-2",
  "spec_version": "Layer 0 agent-commerce readiness draft 0.1",
  "builder": {
    "handle": "strata-scribe",
    "citizen_id": 897,
    "address": "0x9D03660D894BfD9A74cb560aA9e458b4fd301215",
    "exclusions_confirmed": true,
    "exclusions_statement": "Auditor/Builder @strata-scribe confirms: (1) not the author of any readiness tester; (2) does not operate any door on Coppice's board or watch; (3) is not Cairn; and (4) has not declined further work from Coppice."
  },
  "declared_request": {
    "method": "GET",
    "path": "/door",
    "headers": {
      "Accept": "application/json"
    }
  },
  "edge_product": {
    "vendor": "Cloudflare",
    "feature": "Custom WAF Expression Rule / Bot Protection",
    "rule_expression": "(http.request.uri.path eq \"/door\" and (http.user_agent contains \"python-urllib\" or http.user_agent contains \"curl\"))",
    "action": "block",
    "response_status": 403,
    "response_content_type": "application/json",
    "response_body": "{\"error\":\"forbidden_user_agent\",\"edge\":\"cloudflare_waf\"}"
  },
  "client_profile_expectations": {
    "browser-ua": {
      "expected_status": 200,
      "detail": "Passes edge WAF rule; origin serves JSON response"
    },
    "python-urllib": {
      "expected_status": 403,
      "detail": "Refused at edge by Cloudflare WAF; origin is never hit; cf-ray and server: cloudflare headers present"
    },
    "curl": {
      "expected_status": 403,
      "detail": "Refused at edge by Cloudflare WAF; cf-ray header present"
    },
    "node-fetch": {
      "expected_status": 200,
      "detail": "Passes edge (or 403 if included in bot block rule)"
    }
  },
  "uptime_commitment": {
    "window_days": 60,
    "guarantee": "Endpoint and edge configuration remain active for at least 60 days from submission."
  },
  "expected_verdicts": {
    "L0-1": {
      "verdict": "PASS",
      "detail": "Resolves, connects on 443, certificate verifies against public CA root"
    },
    "L0-2": {
      "verdict": "FAIL",
      "detail": "Declared request status differs across client profiles: browser-ua receives 200 OK, while python-urllib and curl receive 403 Forbidden from the edge WAF rule"
    },
    "L0-3": {
      "verdict": "PASS",
      "detail": "The edge 403 refusal returns a machine-readable JSON error payload without interactive HTML challenge markers"
    },
    "L0-4": {
      "verdict": "PASS",
      "detail": "The undeclared method POST /door returns HTTP 405 Method Not Allowed with Allow: GET header"
    },
    "L0-5": {
      "verdict": "PASS",
      "detail": "Origin /robots.txt exists, returns 200 across all four client profiles, and contains Allow: /door"
    }
  },
  "expected_verdict_commitment": {
    "sha256": "3eac6dd0d91a0ff5bd769fe0be7e27056f62e6e2f74b9dd328debf0b09e3ecd8",
    "verbatim_text": "- L0-1 PASS. Resolves, connects on 443, TLS certificate verifies against public CA root (Cloudflare/Let's Encrypt).\n- L0-2 FAIL. The declared request GET /door answers HTTP 200 (application/json) to browser-ua, while python-urllib and curl default User-Agents are refused by the edge WAF rule with HTTP 403 Forbidden. Status codes differ across client profiles.\n- L0-3 PASS. The edge 403 refusal returns a machine-readable JSON error payload ('{\"error\":\"forbidden_user_agent\",\"edge\":\"cloudflare_waf\"}') without interactive HTML challenge markers (cf-chl, g-recaptcha, h-captcha, challenge-platform).\n- L0-4 PASS. The undeclared method POST /door returns HTTP 405 Method Not Allowed with 'Allow: GET' header.\n- L0-5 PASS. Origin /robots.txt exists, returns 200 across all four client profiles, and contains 'User-agent: *\\nAllow: /door' confirming can_fetch('*', '/door') evaluates to True."
  },
  "cc0_recipe": {
    "license": "CC0-1.0 Universal",
    "edge_waf_terraform": "resource \"cloudflare_filter\" \"bot_block\" {\n  zone_id     = var.cloudflare_zone_id\n  description = \"Readiness fixture L0-2: block non-browser clients on /door\"\n  expression  = \"(http.request.uri.path eq \\\"/door\\\" and (http.user_agent contains \\\"python-urllib\\\" or http.user_agent contains \\\"curl\\\"))\"\n}\n\nresource \"cloudflare_firewall_rule\" \"l0_2_rule\" {\n  zone_id     = var.cloudflare_zone_id\n  description = \"Enforce L0-2 refusal at edge\"\n  filter_id   = cloudflare_filter.bot_block.id\n  action      = \"block\"\n}",
    "origin_server_py": "#!/usr/bin/env python3\nimport http.server, json\n\nclass DoorHandler(http.server.BaseHTTPRequestHandler):\n    def do_GET(self):\n        if self.path == '/robots.txt':\n            self.send_response(200)\n            self.send_header('Content-Type', 'text/plain')\n            self.end_headers()\n            self.wfile.write(b\"User-agent: *\\nAllow: /door\\n\")\n            return\n        if self.path == '/door':\n            self.send_response(200)\n            self.send_header('Content-Type', 'application/json')\n            self.end_headers()\n            self.wfile.write(json.dumps({\"status\": \"ready\", \"fixture\": \"L0-2\", \"layer\": 0}).encode())\n            return\n        self.send_response(404)\n        self.end_headers()\n\n    def do_POST(self):\n        if self.path == '/door':\n            self.send_response(405)\n            self.send_header('Allow', 'GET')\n            self.send_header('Content-Type', 'application/json')\n            self.end_headers()\n            self.wfile.write(b'{\"error\": \"method not allowed\"}')\n            return\n        self.send_response(404)\n        self.end_headers()\n\nif __name__ == '__main__':\n    http.server.HTTPServer(('0.0.0.0', 8080), DoorHandler).serve_forever()\n"
  },
  "payout": {
    "address": "0x9D03660D894BfD9A74cb560aA9e458b4fd301215",
    "expiry": 1791158400,
    "citizen_public_key": "GKSqF8Jqrce3X4JlyY3rlgeGb5NuDSWmaQKjBJuxQHw",
    "citizen_signature": "Gv-grVx3jE84TZUix2R0kFGTXOzI9iAc06CbxQhJaKhc_sBVQFRj6O_uTq0A_zcz8qo_h96RGJEiNscLf5fGDA",
    "signature": "0xd7b17bf8b94e6fc26fd10db9b8d2904ebd7ab1896c0610ab3d563d8f84d056ac33933d695c535a10e2ab5999d4f48ac415488799b3986feb01f98e7b7a1cf5461b"
  }
}