Promote Copilot
Copilot reads the count window and names one outcome per rule: Promote, Hold, or Needs allowlist. It never changes WAF mode. A public example of the three cards is on the example Tuning panel.
The three cards
Promote
The watch window is complete and the evidence is one of two shapes: the rule was quiet on a site that had real traffic, or every sample is an attack and the count is covered by that sample. You still click.
Hold
Something is missing, disputed, or unsafe to block. The card says which rule fired. The line under it says what would have to change. Hold does not block.
Needs allowlist
A known-good path is in the sample (login, CMS, API, payment, SSO, or a single crawler path). Allow that exact path if you recognize it, then come back. Copilot does not write the allowlist.
The first matching rule is the one on the card. A later rule does not get a sentence. Each rule is decided on its own. An attack on one rule does not clear a known-good path on another.
Hold and Needs allowlist cards add one line, labeled “What would change this.” Promote cards do not. The line is display only. It does not change the decision, and it does not block anything. It uses the same gap as the count-window timeline. A missing clock, series, or request total says “not confirmed,” never zero.
A public walkthrough of the three cards, with no live site behind it, is the example Tuning panel.
The gates, in order
These are the constants the decision uses.
| Constant | Value | Meaning |
|---|---|---|
| Watch window | 24 hours | The site clock must be closed. Undated sample rows stay in the window. |
| Low traffic | under 50 site requests | A zero count is not “quiet.” Attack samples do not skip this. |
| Review count | 50 counted hits | The tuning card says review. Copilot can still Promote when the samples are attacks and the count is explained. |
| Noisy share | 15% of site requests, and at least 50 hits | Promote only for an explained attack-only sample. |
| Sample factor | 8× | Counted hits must be at most this many times the in-window sample rows. |
| Partial series | under 12 hours of CloudWatch | A closed site clock with a short series is Hold. |
| Many addresses | 5 or more | Used for login floods. The raw IP is never stored. |
| Wide crawler | 3 or more non-attack paths | A search crawler across that many paths is Hold, not an allowlist of the whole site. |
Paths are matched with the query string removed. Attack payloads are classified on the raw URI, including the query and a single URL-decode, before that strip. A scanner path or an injection payload wins over a known-good label and over a spoofed crawler tag. An attack-tool user agent on a known-good path does not.
User-Agent is a hint. sqlmap, nikto, nuclei, and similar tools count as attacks on ordinary paths. Googlebot, Bingbot, and uptime monitors such as UptimeRobot count as known-good. A scanner path or an injection payload still wins.
Which rule fires
- Window open — site clock under 24 hours. Hold, even if the samples are probes.
- Partial series — clock is closed, but CloudWatch covers more than 0 and under 12 hours. Hold.
- Metrics missing — no request total, or the series is not published. Hold. That is not zero traffic.
- Totals disagree — request total is 0 while the rule has counted hits or sample rows. Hold.
- Count disagrees with samples — samples exist and the count is 0. Hold.
- Rate limit — the application DDoS group and the rate-limit rule never Promote and never ask for an allowlist. Login traffic from 5 or more addresses is described as credential stuffing. Any other rate-limit picture stays in count, including a shared campus network.
- Account takeover or signup fraud — those rules, with login, SSO, or registration samples. Hold. An allowlist would turn the rule off for that page.
- Admin protection — it counted an admin or CMS path and the samples are not all attacks. Hold. Copilot will not allowlist the admin path.
- Low traffic — under 50 site requests. Hold, including when a couple of probe rows are present.
- Attack tool on a known-good path — every sample is an attack-tool user agent on a login, payment, SSO, CMS, API, or other known-good path. Hold. Promoting would also block real visitors on that path, and an allowlist would exempt the tool.
- Wide crawler — a search crawler on 3 or more non-attack paths. Hold.
- Bot rule — explained attack-only samples can Promote. An unexplained attack count Holds. Known-good mixed with attacks is Needs allowlist. Anything else, including Googlebot or an uptime check with no attack left beside it, Holds.
- Known-good samples — signature rules with login, CMS, API, payment, SSO, or a single crawler path. Needs allowlist.
- Attack-only, count explained — every sample is a probe path, an injection payload, or an attack-tool user agent on a path that is not known-good, and counted hits are within 8× the sample rows. Promote. One address and many addresses both Promote. The reason says which.
- Attack-only, count not explained — Hold. Unseen requests might be real visitors.
- Counted hits, no sample — Hold.
- Noisy share — 15% or more of traffic, and the samples are not an explained attack. Hold.
- Ambiguous path — a normal path that is not known-good and not an attack. Hold. If the last hour jumped, the reason says that a spike by itself stays on hold.
- Quiet — zero counted hits, no sample rows, a full window, and a published total of at least 50 requests. Promote.
After you save an allowlist
When a saved allowlist covers every known-good sample, Copilot looks again. Rate limits, an open window, and low traffic stay Hold. A remaining path that is not an attack stays Hold. A bot rule with nothing left but the carved-out path stays Hold. A count the sample log cannot explain stays Hold. Otherwise the card says Promote. The allowlist is not a block, and Copilot still does not flip the rule.
What would change this
The line is short. Where the timeline already has a clock or a request total, it fills in the gap. Where that fact was not published, it says not confirmed.
| Reason | Line |
|---|---|
| Window still open | Needs about N more hours or minutes of data, N being the time left in the 24-hour window. A missing clock says how many is not confirmed. |
| Short CloudWatch series | Needs about N more hours of data, N being the time left until 12 hours of CloudWatch. |
| Request total missing | Needs a published CloudWatch series. The request total is not confirmed. |
| Total disagrees with samples | The request total and the samples have to agree. |
| Count disagrees with samples | The counted hits and the sample log have to match. |
| Low traffic | Needs about N more site requests to reach 50, or site requests are not confirmed. |
| Rate limit | This is a rate limit. Keep in count. |
| Credential stuffing | Login attempts from many addresses. Keep in count. |
| Login or signup fraud | An allowlist would turn this off for the login page. Keep in count. |
| Admin path | Admin traffic on an admin page. Keep in count. |
| Attack tool on a sensitive path | Attack-tool traffic on a sensitive path. Keep in count. |
| Wide crawler | A search crawler on several ordinary paths. Keep in count. |
| Needs allowlist | Add an exact-path allowlist if this is your own form. |
| Bot rule held | Every sample has to look like an attack. |
| Count not explained | The samples have to cover the counted hits. |
| No samples | Needs a sample of what was counted. |
| Ambiguous path | The path has to be your own form or a clear attack. |
| Ambiguous spike | The path has to be your own form or a clear attack. A spike by itself stays on hold. |
| Noisy share | Every sample has to be an attack the log can explain. |
| Allowlist left a non-attack | A remaining path has to look like an attack. |
| Allowlist on a bot rule | An attack sample has to show up beside the allowed path. |
| Sample not clear | The sample has to be clear enough to tell an attack from a real visitor. |
Shapes the tests lock
These are the outcomes the decision table is tested against. They are examples of the rules above, not extra rules.
| Situation | Card | Why |
|---|---|---|
| Brochure site, full day, real traffic, zero hits | Promote | Quiet |
| WordPress admin-ajax, Drupal JSON:API, SAML, a payment webhook, or an API post | Needs allowlist | Known-good path |
| UptimeRobot on a health check | Needs allowlist | Known-good monitor path |
| Googlebot on several normal paths | Hold | Wide crawler |
| Bot rule counted only Googlebot | Hold | Not an explained attack |
| sqlmap or an injection payload, count covered by the sample | Promote | Explained attack |
| sqlmap on a login path | Hold | Attack tool on a sensitive path |
| Probe paths are a large share of traffic and the sample covers the count | Promote | Explained attack, even when noisy |
| Rate limit on login from many addresses | Hold | Credential stuffing |
| Account-takeover rule on login | Hold | Allowlisting would turn the rule off |
| Admin protection counted an admin path | Hold | Admin path |
| Checkout posts beside probe paths | Needs allowlist | Mixed |
| That checkout path is saved, probes remain, count is explained | Promote | Allowlist covers the known-good path |
| Allowlist saved, count much larger than the sample | Hold | Count still unexplained |
| 49 or fewer requests, even with a couple of probes | Hold | Low traffic |
| Clock still inside the first day | Hold | Window open |
| Last hour jumped on an ordinary page | Hold | Spike is not enough |
| Last hour jumped and every sample is an injection | Promote | Explained attack |
| No CloudWatch total | Hold | Metrics missing |
| Counted hits and an empty sample log | Hold | No samples |
| A search URL with no attack payload | Hold | Ambiguous |
| Many probe hits and only a couple of sample rows | Hold | Count not explained |
| Rate limit, full day, zero hits | Hold | Rate limits never Promote |