Architecture Decision Records
Architecture Decision Records
An ADR records a decision about the SecLang specification: what was decided, which alternatives existed, and why. Write one whenever the engines disagree and the spec has to pick (Divergence), when behaviour is undocumented but agreed (Clarification), when a legacy feature is retired (Deprecation), or when an engine-specific feature is promoted into the spec (Extension).
Process
- Copy
0000-template.mdtoNNNN-short-slug.mdwith the next free number. - Fill every header field.
Statusisproposeduntil maintainers of at least two implementing engines agree, thenaccepted.supersededandrejectedare terminal. - A
DivergenceADR must list at least one test under## Teststhat encodes the outcome. The validator checks the paths exist. - Add a row to the index below.
uv run python tools/validate.pyfails if a file and the index disagree. - Update the affected section of
spec/in the same PR.
Index
| ADR | Title | Category | Status |
|---|---|---|---|
| 0001 | Status labels and the meaning of Core | Clarification | proposed |
| 0002 | Directive, operator, action and transformation names match case-insensitively | Divergence | proposed |
| 0003 | Test formats: SecRules Test Set JSON for units, go-ftw-derived YAML for engine profiles | Clarification | proposed |
| 0004 | Canonical names and required aliases | Divergence | proposed |
| 0005 | Unknown versus unsupported directives | Divergence | proposed |
| 0006 | Core ctl: options | Divergence | proposed |
| 0007 | Persistent collections are Extended | Divergence | proposed |
| 0008 | Collection keys match case-insensitively | Divergence | proposed |
| 0009 | Strict per-phase evaluation is normative; early evaluation must be invisible | Clarification | proposed |
| 0010 | Engine-specific names are reserved | Clarification | proposed |
| 0011 | ModSecurity v2 legacy features are Deprecated | Deprecation | proposed |
| 0012 | uppercase is promoted to Core | Extension | proposed |
| 0013 | Comment lines ending in a backslash | Divergence | proposed |
| 0014 | SecDefaultAction constraints | Divergence | proposed |
| 0015 | Every rule carries an id | Divergence | proposed |
| 0016 | skipAfter scope ends with the phase | Divergence | proposed |
| 0017 | The default phase is 2 and is never inherited | Divergence | proposed |
| 0018 | Core regular-expression syntax is the RE2-compatible subset | Divergence | proposed |
| 0019 | DURATION is Extended with unspecified units | Clarification | proposed |
| 0020 | JSON argument names are unspecified | Clarification | proposed |
| 0021 | The portable logging contract is rule ids and messages | Clarification | proposed |
| 0022 | REQUEST_BODY without a body processor | Divergence | proposed |
| 0023 | Reference adapters live in this repository | Clarification | proposed |
| 0024 | Unparsable @ipMatch entries are configuration errors | Divergence | proposed |
| 0025 | SecRequestBodyInMemoryLimit is Extended, not Core | Divergence | proposed |
| 0026 | compressWhitespace treats the byte 0xA0 as whitespace | Divergence | proposed |
| 0027 | @rx is compiled dot-all; line anchors need (?m) | Divergence | proposed |
| 0028 | skipAfter resolves to a SecMarker, never to a rule id | Divergence | proposed |
| 0029 | Tag and message rule exceptions select by exact string | Divergence | proposed |
| 0030 | A negated operator applies per value | Clarification | proposed |