Objective
Compile the complete ordered rule-configuration layer used by the stable ModSecurity 3.0.16 / Coraza 3.7.0 union: phase defaults, markers, local includes, authenticated remote rule sources, rule removals, action/target updates, duplicate policy, and explicit compatibility handling for missing update targets. All mutation occurs while building a candidate immutable plan; published plans and the request path remain read-only.
Behavioral contract
Ordered source assembly
- Preserve one deterministic logical directive stream across builder strings, files,
Include, IncludeOptional, and remote sources.
- Local includes retain the WAF-10 canonical-root, cycle, depth, count, size, optional-glob, and source-provenance guarantees.
- Candidate failure cannot alter the active
Waf; publication is atomic after parsing, remote resolution, update application, and validation.
SecDefaultAction
- Store at most one immutable default snapshot per phase and attach rules only to the snapshot for their effective phase.
- Require an explicit valid phase and a non-
block disruptive action.
- Reject duplicate phase defaults with a related span to the first declaration.
- Reject metadata/flow actions and
t:none; preserve ModSecurity-compatible ordered transformation inheritance for other t: actions.
- Rules without
phase remain phase 2; a default for another phase never changes their phase.
- Explicit per-rule actions override singleton defaults while repeatable actions retain specified ordering.
Markers
- Compile
SecMarker into ordered, addressable plan nodes for skipAfter by text or numeric spelling.
- Preserve duplicate names in source order and resolve to the next reachable marker after the executing rule.
- Diagnose unresolved static markers during compilation; dynamic macro-bearing references use bounded runtime lookup.
- Markers execute no operator or action and appear in phase control flow without becoming inspectable rules.
Rule selection and removal
SecRuleRemoveById accepts bounded unsigned IDs and inclusive ranges.
SecRuleRemoveByTag and SecRuleRemoveByMsg use bounded zig-regex selectors, retaining required ModSecurity regex behavior while documenting Coraza equality-only differences.
- Removing a chain head removes the chain; selecting a non-head member is diagnosed rather than creating a partial chain.
- Removed rules leave phase/prefilter runtime indexes while source evidence retains the reason and directive span.
Target updates
SecRuleUpdateTargetById, ByTag, and ByMsg compile selectors once and apply additions/removals in directive order.
- ID selectors support bounded lists and inclusive ranges.
- Target parsing preserves collection, key, regex-key, count, and negation semantics.
- Additions append in order; removals exclude matching prior targets without mutating unrelated targets.
- Updates apply atomically to every selected chain under documented upstream-compatible ownership rules.
Action updates
SecRuleUpdateActionById supports bounded ID lists/ranges and parses its action list once.
id and phase changes are rejected.
- Singleton actions replace the prior effective action of their family; repeatable actions append in source order.
- A disruptive update replaces the prior disruptive action; non-disruptive-only updates preserve it.
- Transformation updates honor ordered
t:none reset semantics and rebuild precomputed pipelines/macros.
Missing targets, duplicates, and compatibility
- Strict mode is default: duplicate external rule IDs, malformed selectors, missing explicitly named IDs, partial-chain mutations, and invalid updates fail with stable diagnostics and primary/related spans.
- An explicit builder compatibility option may ignore only upstream-compatible rule-not-found update/removal cases and emits bounded structured warnings.
- Compatibility mode never suppresses malformed syntax, unsafe remote policy, duplicate IDs, allocation/resource failures, or invariant violations.
- No directive is silently accepted without an effect.
Authenticated remote rules
SecRemoteRules KEY HTTPS_URL resolves only during candidate construction through an injected async-capable fetch interface; transactions perform no network I/O.
- URLs remain credential-free HTTPS and pass explicit host/IP/redirect policy, DNS-rebinding protection, timeout, byte, directive, and redirect limits.
- The key is sent only in the designated authentication header and is redacted from diagnostics, logs, fingerprints, and telemetry.
- Results record final URL, content digest, retrieval metadata, and provenance; identical pinned content may use a bounded cache.
Abort fails the candidate. Warn records a structured warning and continues without substituting stale or empty content unless an explicit pinned-cache policy allows it.
- The transport interface is ready for WAF-42 zig-tls integration; tests use deterministic in-memory transports.
Public and plan interfaces
- Immutable typed rule-selection/update IR with stable source spans and bounded counts/bytes.
- Plan views for effective rules, removal evidence, marker resolution, and configuration warnings.
- Builder limits for selectors, intervals, updates, expansion, markers, remote responses, redirects, and warnings.
- Explicit strict/compatible missing-rule policy and remote host/redirect/cache decisions.
- Stable diagnostics must not renumber WAF-PLAN-0101 through WAF-PLAN-0108.
Deliverables
Acceptance criteria
- Every scoped directive has positive, negative, ordering, allocation-failure, and resource-limit coverage.
- Differential fixtures cover pinned ModSecurity and Coraza behavior; intentional union choices are named and executable.
- CRS 4.28 setup/exclusion streams compile with no unexplained skips.
- Candidate failures leave the active generation unchanged and caller-owned inputs valid.
- Published plans require no update parsing, regex compilation, remote/filesystem/database access, or allocation on the request path.
- Benchmarks record compile cost, plan size, and reload pause for CRS with and without exclusion/update overlays.
- Focused tests, full
zig build test, zig build check, corpus gates, formatting, and hosted CI pass on the exact closing SHA.
- Work lands directly on
main in small conventional commits with issue/commit/run links.
Relationships
Baselines and upstream references
- ModSecurity 3.0.16:
seclang-parser.yy, rules_exceptions.cc, default-action and config-update regressions.
- Coraza 3.7.0:
internal/seclang/directives.go, rule_parser.go, directive engine tests.
- OWASP CRS 4.28.0: setup and rule-exclusion corpus.
- Zig 0.17-dev locked through Pantry; no Git submodules.
Objective
Compile the complete ordered rule-configuration layer used by the stable ModSecurity 3.0.16 / Coraza 3.7.0 union: phase defaults, markers, local includes, authenticated remote rule sources, rule removals, action/target updates, duplicate policy, and explicit compatibility handling for missing update targets. All mutation occurs while building a candidate immutable plan; published plans and the request path remain read-only.
Behavioral contract
Ordered source assembly
Include,IncludeOptional, and remote sources.Waf; publication is atomic after parsing, remote resolution, update application, and validation.SecDefaultActionblockdisruptive action.t:none; preserve ModSecurity-compatible ordered transformation inheritance for othert:actions.phaseremain phase 2; a default for another phase never changes their phase.Markers
SecMarkerinto ordered, addressable plan nodes forskipAfterby text or numeric spelling.Rule selection and removal
SecRuleRemoveByIdaccepts bounded unsigned IDs and inclusive ranges.SecRuleRemoveByTagandSecRuleRemoveByMsguse bounded zig-regex selectors, retaining required ModSecurity regex behavior while documenting Coraza equality-only differences.Target updates
SecRuleUpdateTargetById,ByTag, andByMsgcompile selectors once and apply additions/removals in directive order.Action updates
SecRuleUpdateActionByIdsupports bounded ID lists/ranges and parses its action list once.idandphasechanges are rejected.t:nonereset semantics and rebuild precomputed pipelines/macros.Missing targets, duplicates, and compatibility
Authenticated remote rules
SecRemoteRules KEY HTTPS_URLresolves only during candidate construction through an injected async-capable fetch interface; transactions perform no network I/O.Abortfails the candidate.Warnrecords a structured warning and continues without substituting stale or empty content unless an explicit pinned-cache policy allows it.Public and plan interfaces
Deliverables
Acceptance criteria
zig build test,zig build check, corpus gates, formatting, and hosted CI pass on the exact closing SHA.mainin small conventional commits with issue/commit/run links.Relationships
Baselines and upstream references
seclang-parser.yy,rules_exceptions.cc, default-action and config-update regressions.internal/seclang/directives.go,rule_parser.go, directive engine tests.