[{"data":1,"prerenderedAt":1051},["ShallowReactive",2],{"navigation_docs":3,"-quayel-gateway-testing":91,"-quayel-gateway-testing-surround":1050},[4],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":90},"Quayel Gateway","i-lucide-network","\u002Fquayel-gateway","quayel-gateway",[10,29,68],{"title":11,"icon":12,"path":13,"stem":14,"children":15},"Getting Started","i-lucide-rocket","\u002Fquayel-gateway\u002Fgetting-started","quayel-gateway\u002F01.getting-started\u002Findex",[16,19,24],{"title":17,"path":13,"stem":14,"icon":18},"Introduction","i-lucide-book-open",{"title":20,"path":21,"stem":22,"icon":23},"Installation","\u002Fquayel-gateway\u002Fgetting-started\u002Finstallation","quayel-gateway\u002F01.getting-started\u002F1.installation","i-lucide-container",{"title":25,"path":26,"stem":27,"icon":28},"Project Structure","\u002Fquayel-gateway\u002Fgetting-started\u002Fproject-structure","quayel-gateway\u002F01.getting-started\u002F2.project-structure","i-lucide-folder-tree",{"title":30,"icon":31,"path":32,"stem":33,"children":34},"Plugins","i-lucide-puzzle","\u002Fquayel-gateway\u002Fplugins","quayel-gateway\u002F02.plugins\u002Findex",[35,38,43,48,53,58,63],{"title":36,"path":32,"stem":33,"icon":37},"Overview","i-lucide-workflow",{"title":39,"path":40,"stem":41,"icon":42},"IP Intelligence","\u002Fquayel-gateway\u002Fplugins\u002Fip-intel","quayel-gateway\u002F02.plugins\u002F1.ip-intel","i-lucide-radar",{"title":44,"path":45,"stem":46,"icon":47},"Firewall","\u002Fquayel-gateway\u002Fplugins\u002Ffirewall","quayel-gateway\u002F02.plugins\u002F2.firewall","i-lucide-shield",{"title":49,"path":50,"stem":51,"icon":52},"Rate Limiting","\u002Fquayel-gateway\u002Fplugins\u002Frate-limiting","quayel-gateway\u002F02.plugins\u002F3.rate-limiting","i-lucide-gauge",{"title":54,"path":55,"stem":56,"icon":57},"Cache","\u002Fquayel-gateway\u002Fplugins\u002Fcache","quayel-gateway\u002F02.plugins\u002F4.cache","i-lucide-database",{"title":59,"path":60,"stem":61,"icon":62},"Load Balancer","\u002Fquayel-gateway\u002Fplugins\u002Fload-balancer","quayel-gateway\u002F02.plugins\u002F5.load-balancer","i-lucide-scale",{"title":64,"path":65,"stem":66,"icon":67},"Auto-SSL","\u002Fquayel-gateway\u002Fplugins\u002Fauto-ssl","quayel-gateway\u002F02.plugins\u002F6.auto-ssl","i-lucide-lock",{"title":69,"icon":70,"path":71,"stem":72,"children":73},"AI","i-lucide-bot","\u002Fquayel-gateway\u002Fai","quayel-gateway\u002F03.ai\u002Findex",[74,75,80,85],{"title":36,"path":71,"stem":72,"icon":70},{"title":76,"path":77,"stem":78,"icon":79},"The Quayel Gateway Skill","\u002Fquayel-gateway\u002Fai\u002Fskill","quayel-gateway\u002F03.ai\u002F1.skill","i-lucide-wand-sparkles",{"title":81,"path":82,"stem":83,"icon":84},"Installing the Skill","\u002Fquayel-gateway\u002Fai\u002Finstallation","quayel-gateway\u002F03.ai\u002F2.installation","i-lucide-download",{"title":86,"path":87,"stem":88,"icon":89},"AI Agent Guide","\u002Fquayel-gateway\u002Fai\u002Fagent-guide","quayel-gateway\u002F03.ai\u002F3.agent-guide","i-lucide-braces",false,{"id":92,"title":93,"body":94,"description":1042,"extension":1043,"links":1044,"meta":1045,"navigation":90,"path":1046,"seo":1047,"stem":1048,"__hash__":1049},"docs\u002Fquayel-gateway\u002F08.testing.md","Testing & Validation",{"type":95,"value":96,"toc":1031},"minimark",[97,101,110,113,168,173,206,223,226,256,330,337,475,482,486,640,644,651,755,758,823,846,850,853,870,878,896,909,913,921,927,931,978,991,995,1027],[98,99,93],"h1",{"id":100},"testing-validation",[102,103,104,105,109],"p",{},"The gateway ships a live end-to-end test harness that exercises ",[106,107,108],"strong",{},"every operator, every condition path, and every plugin feature"," against a running gateway — not unit mocks, but real HTTP requests with observable outcomes (status codes, response bodies, log events).",[102,111,112],{},"Two artifacts make this up:",[114,115,116,129],"table",{},[117,118,119],"thead",{},[120,121,122,126],"tr",{},[123,124,125],"th",{},"Artifact",[123,127,128],{},"Purpose",[130,131,132,144,158],"tbody",{},[120,133,134,141],{},[135,136,137],"td",{},[138,139,140],"code",{},"config.all-rules.json",[135,142,143],{},"One gateway config that turns on every feature at once",[120,145,146,151],{},[135,147,148],{},[138,149,150],{},"scripts\u002Ftest-all-rules.sh",[135,152,153,154,157],{},"Boots the stack, fires ",[106,155,156],{},"57 assertions",", prints PASS\u002FFAIL, exits non-zero on any failure",[120,159,160,165],{},[135,161,162],{},[138,163,164],{},"scripts\u002Fall-rules-echo.py",[135,166,167],{},"Minimal echo origin (reports which instance answered) used as upstream",[169,170,172],"h2",{"id":171},"quick-start","Quick start",[174,175,180],"pre",{"className":176,"code":177,"language":178,"meta":179,"style":179},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","cargo build --release\nbash scripts\u002Ftest-all-rules.sh\n","bash","",[138,181,182,198],{"__ignoreMap":179},[183,184,187,191,195],"span",{"class":185,"line":186},"line",1,[183,188,190],{"class":189},"sBMFI","cargo",[183,192,194],{"class":193},"sfazB"," build",[183,196,197],{"class":193}," --release\n",[183,199,201,203],{"class":185,"line":200},2,[183,202,178],{"class":189},[183,204,205],{"class":193}," scripts\u002Ftest-all-rules.sh\n",[102,207,208,209,211,212,211,215,218,219,222],{},"Requirements: ",[138,210,178],{},", ",[138,213,214],{},"curl",[138,216,217],{},"python3",". The script is CI-friendly — it exits ",[138,220,221],{},"0"," only when all 57 assertions pass.",[102,224,225],{},"To keep the stack running after the tests for manual poking:",[174,227,229],{"className":176,"code":228,"language":178,"meta":179,"style":179},"KEEP=1 bash scripts\u002Ftest-all-rules.sh\ncurl http:\u002F\u002F127.0.0.1:8099\u002Flb\u002Frr\n",[138,230,231,249],{"__ignoreMap":179},[183,232,233,237,241,244,247],{"class":185,"line":186},[183,234,236],{"class":235},"sTEyZ","KEEP",[183,238,240],{"class":239},"sMK4o","=",[183,242,243],{"class":193},"1",[183,245,246],{"class":189}," bash",[183,248,205],{"class":193},[183,250,251,253],{"class":185,"line":200},[183,252,214],{"class":189},[183,254,255],{"class":193}," http:\u002F\u002F127.0.0.1:8099\u002Flb\u002Frr\n",[114,257,258,268],{},[117,259,260],{},[120,261,262,265],{},[123,263,264],{},"Component",[123,266,267],{},"Address",[130,269,270,280,290,300,310,320],{},[120,271,272,275],{},[135,273,274],{},"Gateway (HTTP)",[135,276,277],{},[138,278,279],{},"http:\u002F\u002F127.0.0.1:8099",[120,281,282,285],{},[135,283,284],{},"Gateway (HTTPS)",[135,286,287],{},[138,288,289],{},"https:\u002F\u002F127.0.0.1:8499",[120,291,292,295],{},[135,293,294],{},"Echo origin A",[135,296,297],{},[138,298,299],{},"127.0.0.1:9099",[120,301,302,305],{},[135,303,304],{},"Echo origin B",[135,306,307],{},[138,308,309],{},"127.0.0.1:9100",[120,311,312,315],{},[135,313,314],{},"Access log",[135,316,317],{},[138,318,319],{},"\u002Ftmp\u002Fquayel-all-rules-access.jsonl",[120,321,322,325],{},[135,323,324],{},"Gateway log",[135,326,327],{},[138,328,329],{},"\u002Ftmp\u002Fquayel-all-rules-gw.log",[169,331,333,334,336],{"id":332},"what-configall-rulesjson-covers","What ",[138,335,140],{}," covers",[114,338,339,349],{},[117,340,341],{},[120,342,343,346],{},[123,344,345],{},"Area",[123,347,348],{},"Coverage",[130,350,351,390,399,421,456,466],{},[120,352,353,357],{},[135,354,355],{},[106,356,44],{},[135,358,359,360,365,366,211,369,372,373,377,378,381,382,385,386,389],{},"All 15 ",[361,362,364],"a",{"href":363},"\u002Fquayel-gateway\u002Fconditions#operators","operators",", every condition path family (",[138,367,368],{},"req.*",[138,370,371],{},"ip.*",", headers incl. ",[361,374,376],{"href":375},"\u002Fquayel-gateway\u002Fconditions#jwt-claim-extraction","JWT claims",", query, cookie, ",[138,379,380],{},"http.*"," aliases), pure ",[138,383,384],{},"and","\u002F",[138,387,388],{},"or","\u002Fmixed logic chains, all 5 actions",[120,391,392,396],{},[135,393,394],{},[106,395,49],{},[135,397,398],{},"Global catch-all plus single-key, composite, JWT-claim, legacy template, and cookie+query keys; an ip-intel-conditioned rule",[120,400,401,405],{},[135,402,403],{},[106,404,54],{},[135,406,407,408,385,411,385,414,417,418,420],{},"Custom and origin-driven edge TTLs, browser TTL modes (",[138,409,410],{},"custom",[138,412,413],{},"origin",[138,415,416],{},"bypass","), custom variant cache keys, ",[138,419,416],{}," for cookied requests, SWR\u002FSIE, operator conditions",[120,422,423,427],{},[135,424,425],{},[106,426,59],{},[135,428,429,430,211,433,211,436,211,439,211,442,445,446,385,449,385,452,455],{},"All 5 algorithms (",[138,431,432],{},"round_robin",[138,434,435],{},"weighted_round_robin",[138,437,438],{},"least_connections",[138,440,441],{},"fast_response",[138,443,444],{},"sticky_session","), all host-header modes, health-check modes ",[138,447,448],{},"https",[138,450,451],{},"accepts_connections",[138,453,454],{},"off",", a TLS target, and a catch-all pool",[120,457,458,463],{},[135,459,460],{},[106,461,462],{},"Logging",[135,464,465],{},"JSONL file mode with buffered writes",[120,467,468,472],{},[135,469,470],{},[106,471,64],{},[135,473,474],{},"Present but disabled (staging mode) so the full schema is exercised without hitting Let's Encrypt",[102,476,477,478,481],{},"The JWT used by claim-based conditions and keys is a self-signed token with payload ",[138,479,480],{},"{\"user_id\":\"u-42\",\"data\":{\"role\":\"admin\"}}",", minted inline by the harness — no real identity provider needed.",[169,483,485],{"id":484},"the-8-assertion-groups","The 8 assertion groups",[114,487,488,504],{},[117,489,490],{},[120,491,492,495,498,501],{},[123,493,494],{},"#",[123,496,497],{},"Group",[123,499,500],{},"What it proves",[123,502,503],{},"Count",[130,505,506,519,549,570,587,604,615,628],{},[120,507,508,510,513,516],{},[135,509,243],{},[135,511,512],{},"Firewall: all 15 operators",[135,514,515],{},"Each operator matches\u002Fnegates correctly on real requests",[135,517,518],{},"15",[120,520,521,524,527,546],{},[135,522,523],{},"2",[135,525,526],{},"Firewall: condition paths",[135,528,529,530,211,533,211,536,539,540,542,543,545],{},"Every left-hand path family resolves (",[138,531,532],{},"req.host",[138,534,535],{},"req.ip",[138,537,538],{},"req.peer_ip",", JWT claims, ",[138,541,380],{}," aliases, all ",[138,544,371],{}," fields)",[135,547,548],{},"16",[120,550,551,554,557,567],{},[135,552,553],{},"3",[135,555,556],{},"Firewall: logic + actions",[135,558,559,560,563,564],{},"OR chains match any branch; mixed AND\u002FOR composes; ",[138,561,562],{},"redirect"," returns the configured status + ",[138,565,566],{},"Location",[135,568,569],{},"6",[120,571,572,575,578,585],{},[135,573,574],{},"4",[135,576,577],{},"Header-injection visibility",[135,579,580,581,584],{},"A firewall ",[138,582,583],{},"set_request_header"," is visible to later plugins (proven via a rate-limit key)",[135,586,243],{},[120,588,589,592,595,602],{},[135,590,591],{},"5",[135,593,594],{},"Rate limiting: key modes",[135,596,597,598,601],{},"Every key mode buckets independently and returns 429 after ",[138,599,600],{},"limit"," requests",[135,603,569],{},[120,605,606,608,610,613],{},[135,607,569],{},[135,609,54],{},[135,611,612],{},"MISS→HIT behavior across TTL modes, variant keys, and bypass",[135,614,591],{},[120,616,617,620,623,626],{},[135,618,619],{},"7",[135,621,622],{},"Load balancer",[135,624,625],{},"Round robin alternates targets, sticky sessions pin, every algorithm routes",[135,627,591],{},[120,629,630,633,635,638],{},[135,631,632],{},"8",[135,634,462],{},[135,636,637],{},"JSONL events written for cache hits, rate limits, and every expected firewall action",[135,639,553],{},[169,641,643],{"id":642},"how-assertions-work","How assertions work",[102,645,646,647,650],{},"The harness uses four assertion helpers, each keyed on an ",[106,648,649],{},"observable outcome",":",[174,652,654],{"className":176,"code":653,"language":178,"meta":179,"style":179},"assert_status  \"name\" 200        curl-args...   # exact status code\nassert_block   \"name\" 403 rule-id curl-args...  # status + rule_id in the JSON block body\nassert_action  \"name\" rule-id Action curl-args... # request passes (200) AND the action\n                                                  # appears in the access log\nrl_burst       \"name\" N          curl-args...   # N-th request in a burst is 429\n",[138,655,656,681,705,727,733],{"__ignoreMap":179},[183,657,658,661,664,667,670,674,677],{"class":185,"line":186},[183,659,660],{"class":189},"assert_status",[183,662,663],{"class":239},"  \"",[183,665,666],{"class":193},"name",[183,668,669],{"class":239},"\"",[183,671,673],{"class":672},"sbssI"," 200",[183,675,676],{"class":193},"        curl-args...",[183,678,680],{"class":679},"sHwdD","   # exact status code\n",[183,682,683,686,689,691,693,696,699,702],{"class":185,"line":200},[183,684,685],{"class":189},"assert_block",[183,687,688],{"class":239},"   \"",[183,690,666],{"class":193},[183,692,669],{"class":239},[183,694,695],{"class":672}," 403",[183,697,698],{"class":193}," rule-id",[183,700,701],{"class":193}," curl-args...",[183,703,704],{"class":679},"  # status + rule_id in the JSON block body\n",[183,706,708,711,713,715,717,719,722,724],{"class":185,"line":707},3,[183,709,710],{"class":189},"assert_action",[183,712,663],{"class":239},[183,714,666],{"class":193},[183,716,669],{"class":239},[183,718,698],{"class":193},[183,720,721],{"class":193}," Action",[183,723,701],{"class":193},[183,725,726],{"class":679}," # request passes (200) AND the action\n",[183,728,730],{"class":185,"line":729},4,[183,731,732],{"class":679},"                                                  # appears in the access log\n",[183,734,736,739,742,744,746,749,752],{"class":185,"line":735},5,[183,737,738],{"class":189},"rl_burst",[183,740,741],{"class":239},"       \"",[183,743,666],{"class":193},[183,745,669],{"class":239},[183,747,748],{"class":193}," N",[183,750,751],{"class":193},"          curl-args...",[183,753,754],{"class":679},"   # N-th request in a burst is 429\n",[102,756,757],{},"Blocked responses carry the rule identity in the body, which is what makes assertions precise:",[174,759,763],{"className":760,"code":761,"language":762,"meta":179,"style":179},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\"error\":\"blocked\",\"status\":403,\"rule_id\":\"fw-op-contains\"}\n","json",[138,764,765],{"__ignoreMap":179},[183,766,767,770,772,776,778,780,782,785,787,790,792,795,797,799,802,804,806,809,811,813,815,818,820],{"class":185,"line":186},[183,768,769],{"class":239},"{",[183,771,669],{"class":239},[183,773,775],{"class":774},"spNyl","error",[183,777,669],{"class":239},[183,779,650],{"class":239},[183,781,669],{"class":239},[183,783,784],{"class":193},"blocked",[183,786,669],{"class":239},[183,788,789],{"class":239},",",[183,791,669],{"class":239},[183,793,794],{"class":774},"status",[183,796,669],{"class":239},[183,798,650],{"class":239},[183,800,801],{"class":672},"403",[183,803,789],{"class":239},[183,805,669],{"class":239},[183,807,808],{"class":774},"rule_id",[183,810,669],{"class":239},[183,812,650],{"class":239},[183,814,669],{"class":239},[183,816,817],{"class":193},"fw-op-contains",[183,819,669],{"class":239},[183,821,822],{"class":239},"}\n",[102,824,825,826,211,829,211,831,834,835,837,838,841,842,845],{},"Pass-through actions (",[138,827,828],{},"allow",[138,830,583],{},[138,832,833],{},"set_response_header",") don't stop the request, so ",[138,836,710],{}," asserts two things at once: the request reached the origin (status 200) and the firewall action was written to the JSONL log. A final sweep verifies that ",[106,839,840],{},"every"," expected ",[138,843,844],{},"(rule_id, action)"," pair appears in the log.",[169,847,849],{"id":848},"verified-behaviors","Verified behaviors",[102,851,852],{},"The suite pins down several semantics that are easy to get wrong:",[854,855,856,861,862,865,866,869],"note",{},[106,857,858,860],{},[138,859,583],{}," lives in the request context, not on the upstream request."," Injected headers are visible to later plugins — condition resolution, rate-limit keys, cache keys — but are ",[106,863,864],{},"not"," forwarded to the upstream request. The gateway adds its own ",[138,867,868],{},"X-Forwarded-*"," headers upstream. Group 4 proves this: a rate-limit rule keyed on the injected header buckets per injected value.",[854,871,872,877],{},[106,873,874,876],{},[138,875,833],{}," is currently a no-op on the wire."," The rule matches, is logged, and the request continues — but no response header is set. Treat it as reserved for future use.",[879,880,881,887,888,891,892,895],"tip",{},[106,882,883,884],{},"Rate-limiting rules may have empty ",[138,885,886],{},"conditions"," (a global limit applies to every request), while ",[106,889,890],{},"firewall rules must declare at least one condition"," — startup rejects empty firewall conditions. Use a rate-limit rule with ",[138,893,894],{},"\"conditions\": []"," for catch-all quotas.",[897,898,899,902,903,905,906,908],"caution",{},[106,900,901],{},"First match wins — even for pass-through actions."," A matched ",[138,904,828],{}," or ",[138,907,583],{}," rule stops evaluation of later rules. Order your rules from specific to general.",[169,910,912],{"id":911},"reading-the-output","Reading the output",[174,914,919],{"className":915,"code":917,"language":918},[916],"language-text","════════════════════════ ALL-RULES RESULTS ════════════════════════\n  PASS  op:equals(req.method)                       status=421 want=421\n  PASS  op:not_equals(req.scheme)                   status=200 rule=fw-op-not-equals action=SetRequestHeader\n  ...\n  PASS  logging:firewall action events for all rules expected=18 missing=0\n────────────────────────────────────────────────────────────────────\n  TOTAL: 57   PASS: 57   FAIL: 0\n════════════════════════════════════════════════════════════════════\n","text",[138,920,917],{"__ignoreMap":179},[102,922,923,924,926],{},"Each line shows the observed value next to the expectation, so a failure is diagnosable from the report alone. On any failure the script exits ",[138,925,243],{},".",[169,928,930],{"id":929},"extending-the-suite","Extending the suite",[932,933,934,956,961,968],"ol",{},[935,936,937,938,940,941,944,945,948,949,948,952,955],"li",{},"Add the feature to ",[138,939,140],{}," (give the rule a descriptive ",[138,942,943],{},"id"," like ",[138,946,947],{},"fw-op-…"," \u002F ",[138,950,951],{},"rl-…",[138,953,954],{},"cache-…",").",[935,957,958,959,926],{},"Add an assertion to the matching group in ",[138,960,150],{},[935,962,963,964,967],{},"For pass-through firewall actions, register the expectation with ",[138,965,966],{},"expect_log \u003Crule_id> \u003CAction>"," so the final log sweep covers it.",[935,969,970,971,974,975,926],{},"Re-run — the report must show ",[138,972,973],{},"FAIL: 0",", and the new assertion must be counted in ",[138,976,977],{},"TOTAL",[879,979,980,981,984,985,987,988,990],{},"Run with ",[138,982,983],{},"KEEP=1"," and poke the gateway by hand with ",[138,986,214],{}," while tailing ",[138,989,319],{}," — the JSONL stream shows exactly how each request was evaluated.",[169,992,994],{"id":993},"related","Related",[996,997,998,1005,1011,1022],"ul",{},[935,999,1000,1004],{},[361,1001,1003],{"href":1002},"\u002Fquayel-gateway\u002Fconditions","Conditions"," — operators, paths, and logic chains the suite exercises",[935,1006,1007,1010],{},[361,1008,462],{"href":1009},"\u002Fquayel-gateway\u002Flogging"," — the JSONL format assertions are matched against",[935,1012,1013,1017,1018,1021],{},[361,1014,1016],{"href":1015},"\u002Fquayel-gateway\u002Fversioning","Versioning"," — ",[138,1019,1020],{},"config_version"," conventions used by the test config",[935,1023,1024,1026],{},[361,1025,86],{"href":87}," — machine-readable contract validated by this suite",[1028,1029,1030],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}",{"title":179,"searchDepth":200,"depth":200,"links":1032},[1033,1034,1036,1037,1038,1039,1040,1041],{"id":171,"depth":200,"text":172},{"id":332,"depth":200,"text":1035},"What config.all-rules.json covers",{"id":484,"depth":200,"text":485},{"id":642,"depth":200,"text":643},{"id":848,"depth":200,"text":849},{"id":911,"depth":200,"text":912},{"id":929,"depth":200,"text":930},{"id":993,"depth":200,"text":994},"The all-rules config and 57-assertion live test suite that proves every documented behavior.","md",null,{},"\u002Fquayel-gateway\u002Ftesting",{"title":93,"description":1042},"quayel-gateway\u002F08.testing","MfSZJY5l0BaDQYaO2hy6XEYmUW6VLtlIGv3T4FYpEbw",[1044,1044],1791649769266]