Zeq Edge · Rule Engine
Per-site rules are stored in cf_rules and evaluated in ascending priority at request-time by the edge process (shared/cf-edge/). First match wins. The rule chain runs before the built-in WAF gate — explicit allow / deny / redirect short-circuits the WAF.
Rule shape
{
id: string, // UUID — server-assigned
kind: "page_rule" | "waf" | "redirect",
match_pattern: string, // path prefix; "*" valid for waf
action_json: Record<string, unknown>, // kind-specific (below)
priority: number, // 0..100000; unique per site
enabled: boolean, // disabled rules are skipped
created_at_zeqond: bigint
}
Match semantics
page_rule and redirect match by path prefix, where the prefix is treated as the literal match_pattern OR match_pattern + "/" to prevent /admin from accidentally matching /administrator.
waf accepts "*" (always — pure WAF guard) OR a path prefix (gates a path). A waf rule additionally requires req.wafComposite >= threshold (action_json.threshold or the default 0.5). If wafComposite is unset (no edge has computed it yet), waf rules never match.
Action shapes by kind
page_rule
action_json | Result |
|---|---|
{ deny: true } | 403, audit row CF-RULE-DENY. |
{ cache_ttl_zeqonds: 600 } | Mark as cacheable with TTL 600 Zeqonds (≈ 466 s). |
{} (default) | Explicit allow — short-circuits remaining rules, continues to WAF. |
waf
action_json | Result |
|---|---|
{ threshold: 0.85 } | If composite ≥ 0.85, deny + audit row CF-WAF-BLOCK. |
{} | Uses default threshold (CF_WAF_COMPOSITE_THRESHOLD = 0.5). |
redirect
action_json | Result |
|---|---|
{ target: "/new", status: 301 } | 301 Location: /new |
{ target: "/", status: 308 } | 308 Location: / (default status if missing) |
Examples
Deny /admin/* (priority 10 — runs ahead of cache and WAF):
{ "kind": "page_rule", "match_pattern": "/admin", "action_json": { "deny": true }, "priority": 10 }
Cache /static/* for 1 hour (3600 s ≈ 4633 Zeqonds; round to 4633):
{ "kind": "page_rule", "match_pattern": "/static", "action_json": { "cache_ttl_zeqonds": 4633 }, "priority": 50 }
Permanent redirect old → new:
{ "kind": "redirect", "match_pattern": "/old-path", "action_json": { "target": "/new-path", "status": 301 }, "priority": 20 }
Aggressive WAF on /api/* (lower threshold than default):
{ "kind": "waf", "match_pattern": "/api", "action_json": { "threshold": 0.35 }, "priority": 30 }
Built-in WAF gate (the default if no rule matched)
After the per-site rule chain finishes with no match, the edge runs the three-gate:
fired = composite_score ≥ θ_composite (θ_composite = 0.85 default)
∧ protect001(phase) ≥ protect001_min (= 0.388 default)
∧ protect001_low ≤ protect002(t) ≤ protect001_high (≈ [0.2, 0.8])
A fired result is a block — the audit row is CF-WAF-BLOCK and a cf.threat.blocked subscription fans out to the publisher machine's subscribers (existing subscriptionFan.fireSubscription primitive).
The composite uses the doctrine-default HF1-HF20 weights from lib/avComposite.ts:
w₅ = w₁₆ = w₂₀ = 0.1667(prioritised — legal / ethical / binomial truth)w_other = 0.0294(17 ordinary HFs)Σwᵢ = 0.9999— passes the framework's 0.1 % gate (KO42)
Phase 2.1 wires a narrow feature extractor (Shannon entropy + path-pattern heuristic). Phase 2.2 promotes to the full 4-stage ZSP envelope (K_spectral + HF + K_temporal + K_chaos) per routes/zsp.ts.