跳至主要内容

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_jsonResult
{ 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_jsonResult
{ threshold: 0.85 }If composite ≥ 0.85, deny + audit row CF-WAF-BLOCK.
{}Uses default threshold (CF_WAF_COMPOSITE_THRESHOLD = 0.5).

redirect

action_jsonResult
{ 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.