zig-waf

Disruptive, flow, and runtime control actions

WAF-15 compiles disruptive decisions, flow metadata, and runtime controls into immutable plan ABI 7. A matched standalone rule or complete chain stages these decisions together with WAF-14 metadata, captures, TX/ENV writes, persistent mutations, and owned event evidence. Expansion, lifecycle, capability, persistence, allocation, or intervention errors publish none of that state.

The runtime supports allow (transaction, request, and phase scope), block, deny, drop, pass, capability-gated proxy, redirect, and status. block resolves its phase default during compilation. Redirect status falls back to 302 unless it is 301, 302, 303, or 307. Detection-only decisions retain the same owned evidence but do not interrupt a phase or terminate inspection.

PhaseCursor traverses immutable same-phase chain heads without steady-state allocation. Numeric skip counts only executable heads. Static and dynamic skipAfter values resolve to the first later same-name marker; dynamic values see effects staged by the matching rule. All allow scopes leave phase-5 logging reachable.

Transaction-local controls cover rule engine, audit engine and parts, request body access/limit/processor, force-request-body, response-body access and processor, rule ID and tag exclusions, and exact or regex-delimited target exclusions by ID or tag. Body controls reject changes after their consumption boundary; ctl:responseBodyProcessor is accepted through the response-headers phase and selects the response body processor (JSON flattens into RESPONSE_ARGS), since responses have no Content-Type auto-detection. Exclusions are bounded by count and owned bytes and affect only subsequent evaluation. Regex target selectors compile through the pinned zig-regex dependency and use pointer-stable compiled programs with isolated per-transaction workers; matcher limits surface as explicit transaction errors.

The connector ABI reserves explicit pause capability/intervention tags so a connector cannot silently treat pause as pass. Parsing a duration, enforcing a configured duration bound, and scheduling nonblocking pause execution are owned by WAF-21; WAF-15 does not publish a partially functional pause action.

Executable evidence is recorded in src/compatibility/evidence/disruptive-flow-controls.json. CI runs unit and integration tests, the pinned five-root plan corpus, 10,000 deterministic action fuzz cases, and ReleaseFast action benchmarks.

The closing ReleaseFast run on the development host (5,000 iterations per scenario) measured the no-op cursor at p99 250 ns with zero operation allocations, dynamic skipAfter at p99 42 ns with zero operation allocations, and exclusion-heavy traversal plus a regex target probe at p99 292 ns. The last scenario records four bounded first-use matcher-cache allocations (142 bytes) per transaction; cursor traversal itself only advances immutable plan slices and transaction-local counters.

The implementation gate passed the complete hosted workflow on commit 0b803704e22b8c5b86c4f4927fe555d3542fb83f, including dependency-lock and no-submodule checks, 219 tests, the pinned CRS/ModSecurity/Coraza corpora, 10,000-case fuzz steps, and all ReleaseFast benchmarks.