diff --git a/docs/adr/0001-standalone-rust-gateway-workspace-core.md b/docs/adr/0001-standalone-rust-gateway-workspace-core.md new file mode 100644 index 0000000..7c4a530 --- /dev/null +++ b/docs/adr/0001-standalone-rust-gateway-workspace-core.md @@ -0,0 +1,64 @@ +# ADR 0001: Standalone Rust gateway with in-workspace `waf-ids-core` + +- Status: Accepted +- Date: 2026-08-25 +- Recorded from: current `main` (`README.md` workspace notes; + `docs/architecture.md` components and security boundaries; root + `Cargo.toml` workspace members) + +## Context + +wardnet (crate name `waf-ids-ai-soc`) is the WAF / IDS / AI SOC gateway +and control-plane leaf for ContextualWisdomLab. Operators need a binary +that starts, serves management and gateway HTTP, and scores requests +without checking out sibling products. + +Domain logic (models, validation, upserts, scoring, DNSBL zone text, +event retention, feed freshness, KPI snapshots) is reusable. Splitting +that logic into a git submodule before an independently versioned +engine or SDK exists would add release and review overhead without an +external consumer. + +Cargo workspaces keep multiple packages on one lockfile and one +`cargo test --workspace` surface (The Cargo Book, n.d.). + +## Decision + +1. Ship a **standalone Rust gateway**. The process runs by itself with + optional operator configuration. No sibling checkout is required. +2. Keep reusable domain code in **`crates/waf-ids-core`**, a member of + the same Cargo workspace (`path` dependency), not a git submodule, + until an independently versioned engine, SDK, or adapter needs its + own release lifecycle. +3. Treat sibling ContextualWisdomLab products as **optional composition + callers** over HTTP or documented contracts: + - **naruon** and **gyeot** may call or be called when an operator + wires them; they are not required tree members. + - **contextual-orchestrator** is the intended front door for the + optional SOC LLM path. Current `main` exposes the `SocLlmConfig` + runtime hook, but `run_from_env` does **not** yet wire + `SOC_LLM_BASE_URL`; absent explicit in-process configuration, SOC + assist stays off. + - **Clearfolio** is an optional document-viewer relay target. + Current `main` exposes the `ClearfolioConfig` runtime hook, but + `run_from_env` does **not** yet wire `CLEARFOLIO_BASE_URL`; + absent explicit in-process configuration, that surface stays + disabled. + Existing optional caller links stay in place. Do not require those + services to start the gateway. + +## Consequences + +- Operators can `cargo run` and use `/admin`, `/gateway/{path}`, and + `/dnsbl/zone` on a single binary. +- `waf-ids-core` stays free of async/HTTP dependencies so domain tests + and fuzz mirrors do not pull the Axum crate graph. +- A later submodule or crates.io publish is deferred until a real + second consumer and release cadence exist. +- Optional Clearfolio and orchestrator hooks must remain inert when + unconfigured so the leaf stays independently runnable. + +## References + +The Cargo Book. (n.d.). *Workspaces*. +https://doc.rust-lang.org/cargo/reference/workspaces.html diff --git a/docs/adr/0002-optional-json-state-standalone-durability.md b/docs/adr/0002-optional-json-state-standalone-durability.md new file mode 100644 index 0000000..bbaae07 --- /dev/null +++ b/docs/adr/0002-optional-json-state-standalone-durability.md @@ -0,0 +1,55 @@ +# ADR 0002: Optional JSON state for standalone durability + +- Status: Accepted +- Date: 2026-08-25 +- Recorded from: current `main` (`README.md` run notes; + `docs/architecture.md` security boundaries; `docs/runbooks/operations.md` + persistence behavior) + +## Context + +The gateway must keep operator-managed routes, threat indicators, DNSBL +entries, events, and license metadata across a local restart when an +operator asks for durability. Many lab and smoke runs do not need a +file at all. + +JSON is the Internet Standard data interchange format for this class of +text documents (Bray, 2017, RFC 8259 / STD 90). A single pretty-printed +object is enough for a standalone process. It is not a multi-operator +database, a backup system, or an audited change workflow. + +## Decision + +1. `WAF_IDS_STATE_PATH` is **optional**. When unset, the process uses + seeded in-memory state. Health reports `persistence: memory`. +2. When the path is set, load JSON from that file (or seed and create + it). Persist with a **temporary sibling file** and **atomic rename** + onto the configured path. Health reports `persistence: file`. +3. If a management write cannot replace the state file, **roll back** + the in-memory mutation and return an operator-visible error. +4. Treat this JSON file as **baseline standalone durability only**. It + is not a production control-plane database, not a backup plan, and + not an audited change-management system. + +A production database is **not** an accepted architecture decision on +current `main`. + +## Consequences + +- `scripts/smoke.sh` can prove restart persistence with a temporary + JSON file and no external datastore. +- Parse failures on a configured path fail startup rather than silently + ignoring a corrupt file (`docs/security/threat-model.md`). +- Concurrent writers and disaster recovery remain out of scope until a + later durable store is accepted. +- Schema evolution is the application's JSON shape, not a migration + framework. + +## References + +Bray, T. (Ed.). (2017). *The JavaScript Object Notation (JSON) data +interchange format* (RFC 8259). RFC Editor. +https://doi.org/10.17487/RFC8259 + +*(Internet Standard, STD 90. Live-checked 2026-08-25 via +https://www.rfc-editor.org/info/rfc8259 and the DOI above.)* diff --git a/docs/adr/0003-owasp-crs-coraza-waf-authority.md b/docs/adr/0003-owasp-crs-coraza-waf-authority.md new file mode 100644 index 0000000..1c659f1 --- /dev/null +++ b/docs/adr/0003-owasp-crs-coraza-waf-authority.md @@ -0,0 +1,73 @@ +# ADR 0003: OWASP CRS / Coraza as WAF authority + +- Status: Accepted +- Date: 2026-08-25 +- Recorded from: current `main` (`README.md` production-coverage note; + `docs/architecture.md` near-term WAF integration) + +## Context + +The gateway scores requests from local threat indicators and DNSBL +entries. That baseline is not a replacement for a maintained WAF rule +set. Inventing an in-house rule language would duplicate work the +OWASP Core Rule Set already does for generic attack detection +(OWASP Foundation / CRS Project, n.d.). + +OWASP Coraza is an open-source WAF engine documented as compatible +with OWASP CRS (OWASP Coraza, n.d.). Current `main` already accepts +Coraza/CRS **audit** documents; it does not embed Coraza in-process. + +## Decision + +1. **OWASP CRS remains the WAF rule authority.** Do not replace CRS + with a hand-rolled rule engine or claim that Wardnet's local + signatures are equivalent to CRS. +2. Accept admin-authenticated Coraza / OWASP CRS **audit JSON/NDJSON** + at `POST /api/waf/coraza/audit`. Interrupted transactions and CRS + rule messages become `SecurityEvent` rows. Block-grade hits may seed + DNSBL and `client_ip` / path threat indicators so later gateway + decisions can enforce matching clients. +3. Run Coraza **outside** this process for now. **In-process Coraza + embedding is a follow-up**, not an accepted replacement of CRS and + not an accepted replacement of the audit ingest path. +4. Current `main` may still apply bounded built-in signatures and a + lightweight anomaly heuristic during gateway scoring. Those are + supplemental local heuristics for first-pass triage and blocking; + they are **not** presented as WAF authority, CRS parity, or a + substitute for Coraza-backed enforcement. + Bitussi and Doriguzzi-Corin (2026) show why HTTP anomaly detection + benefits from explainable, model-backed request analysis but also + why detector quality depends on trustworthy training data and + calibration. Wardnet therefore keeps its lightweight scoring path + explicitly bounded and subordinate to CRS authority rather than + claiming heuristic parity with a maintained WAF rule set. + +Related accepted ingest on the same `main` (IDS, not WAF authority): +admin-authenticated Suricata EVE JSON/NDJSON at +`POST /api/ids/suricata/eve` (Eve JSON output, n.d.). Full route +correlation and live EVE tailing remain follow-ups. + +## Consequences + +- Operators can attach an external Coraza/CRS deployment and still use + this gateway for scoring, events, and route-scoped block mode. +- CRS versioning and rule quality stay with the CRS project (latest + line observed 2026-08-25: 4.29.0 on https://coreruleset.org/). +- Embedding Coraza later must still consume CRS; it must not become a + pretext for a parallel hand-written rule pack. + +## References + +OWASP Coraza. (n.d.). *Documentation*. https://coraza.io/docs/ + +OWASP Coraza. (n.d.). *OWASP Coraza WAF*. https://coraza.io/ + +OWASP Foundation / CRS Project. (n.d.). *OWASP Core Rule Set*. +https://coreruleset.org/ + +Eve JSON output. (n.d.). In *Suricata documentation*. +https://docs.suricata.io/en/latest/output/eve/eve-json-output.html + +Bitussi, M., & Doriguzzi-Corin, R. (2026). *X-WAD: eXplainable web +anomaly detection* [Preprint]. arXiv. +https://arxiv.org/abs/2608.27172 diff --git a/docs/adr/0004-rfc-5782-style-dnsbl-zone-export.md b/docs/adr/0004-rfc-5782-style-dnsbl-zone-export.md new file mode 100644 index 0000000..2efc183 --- /dev/null +++ b/docs/adr/0004-rfc-5782-style-dnsbl-zone-export.md @@ -0,0 +1,69 @@ +# ADR 0004: RFC 5782-style DNSBL zone export + +- Status: Accepted +- Date: 2026-08-25 +- Recorded from: current `main` (`README.md` DNSBL notes; + `docs/architecture.md` `/dnsbl/zone` and DNSBL serving follow-up; + `docs/fuzzing.md` zone-export invariants) + +## Context + +Operators publish listed addresses so mail and gateway scorers can +query a DNS blacklist. Levine (2010) describes DNS blacklists and +whitelists as **IRTF Informational** practice: this is **not** an +Internet Standards Track specification. The conventional listing +record is an A resource record whose address is a **response code**, +not a destination to connect to. Those A values SHOULD lie in +`127.0.0.0/8` so a mistaken use as an IP address stays on loopback +(Levine, 2010, RFC 5782). + +Zone and resource-record structure follows DNS concepts and the DNS +implementation specification (Mockapetris, 1987a, RFC 1034 / STD 13; +Mockapetris, 1987b, RFC 1035 / STD 13). + +## Decision + +1. Export an **RFC 5782-style DNSBL zone** at `GET /dnsbl/zone` using + the configured `DNSBL_ORIGIN`. The `dnsbl.local` default is for local + development only; authoritative deployments must explicitly configure a + non-`.local` origin because `.local.` is reserved for mDNS. +2. Require every published DNSBL **response code** to be an IPv4 + loopback-style address in **`127.0.0.0/8`**. Reject codes outside + that range at the management API. +3. Treat the export as **zone text suitable for an authoritative DNS + server**. This process does **not** serve DNS on port 53. +4. **Hickory DNS authoritative serving is a follow-up**, to be + considered after zone-export semantics stabilize. It is not + accepted on current `main`. + +## Consequences + +- Management upserts stay keyed by listed `address`; the A-record + payload is the validated `127.0.0.0/8` code. +- Fuzz and property tests require every published A-record code to + remain a loopback literal and every TXT payload to stay escaped + (`docs/fuzzing.md`). +- RFC 5782 remains Informational. Local validation is stricter + (`MUST` in this gateway) than the RFC `SHOULD` on A values. +- IPv6 DNSxL layout in RFC 5782 is not an accepted serving mode here. + +## References + +Cheshire, S., & Krochmal, M. (2013). *Multicast DNS* (RFC 6762). +RFC Editor. https://doi.org/10.17487/RFC6762 + +Levine, J. (2010). *DNS blacklists and whitelists* (RFC 5782). RFC +Editor. https://doi.org/10.17487/RFC5782 + +*(IRTF Informational; not Standards Track. Also +https://www.rfc-editor.org/info/rfc5782. Live-checked 2026-08-25.)* + +Mockapetris, P. (1987a). *Domain names—concepts and facilities* +(RFC 1034). RFC Editor. https://doi.org/10.17487/RFC1034 + +*(Internet Standard, STD 13.)* + +Mockapetris, P. (1987b). *Domain names—implementation and +specification* (RFC 1035). RFC Editor. https://doi.org/10.17487/RFC1035 + +*(Internet Standard, STD 13.)* diff --git a/docs/adr/0005-coverage-guided-fuzzing-untrusted-inputs.md b/docs/adr/0005-coverage-guided-fuzzing-untrusted-inputs.md new file mode 100644 index 0000000..14a5b79 --- /dev/null +++ b/docs/adr/0005-coverage-guided-fuzzing-untrusted-inputs.md @@ -0,0 +1,73 @@ +# ADR 0005: Coverage-guided fuzzing of untrusted-input surfaces + +- Status: Accepted +- Date: 2026-08-25 +- Recorded from: current `main` (`docs/fuzzing.md`; README verification + note; in-repo preprint PDF + `docs/papers/fuzzing-art-science-engineering-survey-arxiv-1812.00140.pdf`) + +## Context + +The gateway parses attacker-controlled path, query, body, and client +IP on every request. Startup also deserializes untrusted JSON state +and admin-token configuration. DNSBL zone generation emits text from +operator-supplied reasons and codes. + +Manès et al. (2021) survey fuzzing as repeated execution with +generated, often malformed inputs, and treat coverage-guided fuzzing +as a primary engineering method for finding crashes and invariant +violations on those surfaces. This ADR cites that **published** IEEE +Transactions on Software Engineering article as primary. The 2018 +arXiv posting is the **preprint** of the same work (Manès et al., +2018) and is already vendored in-repo. No other fuzzing paper is +cited. + +## Decision + +1. Exercise the untrusted-input surfaces with **coverage-guided + fuzzing** (cargo-fuzz / libFuzzer) on nightly: + - `fuzz_score_request` — `waf_ids_core::score_request` + - `fuzz_appdata_json` — `AppData` state-file JSON + - `fuzz_parse_admin_tokens` — admin-token configuration parser + - `fuzz_dnsbl_zone` — DNSBL zone export / validation +2. Keep a **stable property-test mirror** (`proptest`) in + `crates/waf-ids-core/tests/fuzz_invariants.rs` and + `tests/fuzz_invariants.rs` so the same invariants run on stable in + `cargo test --workspace`. +3. Isolate fuzz targets in the `fuzz/` Cargo workspace so root + `cargo test --workspace` never builds libFuzzer targets. +4. When an untrusted-input surface changes, keep the libFuzzer target + and the property-test mirror in sync (`docs/fuzzing.md`). + +## Consequences + +- Invariants include: no panic on arbitrary valid UTF-8 JSON input for the + state parser; non-empty score + reasons; deterministic scoring; serde round-trip of parsed state; + no empty token key or empty actor; TXT payloads fully escaped; + every published A-record code in `127.0.0.0/8`. +- Pull-request CI smoke-fuzzes each target for a bounded budget; + nightly runs a longer budget. Those workflows are operational, not + additional papers. +- Coverage-gate stubs and cancelled scanner runs are not evidence for + this decision. + +## References + +Manès, V. J. M., Han, H., Han, C., Cha, S. K., Egele, M., Schwartz, +E. J., & Woo, M. (2021). The art, science, and engineering of +fuzzing: A survey. *IEEE Transactions on Software Engineering, +47*(11), 2312–2331. https://doi.org/10.1109/TSE.2019.2946563 + +*(Primary published version. Crossref record confirmed 2026-08-25: +title, volume 47 issue 11, pages 2312–2331, date 2021-11-01. DOI +resolver reached `https://ieeexplore.ieee.org/document/8863940/`.)* + +Manès, V. J. M., Han, H., Han, C., Cha, S. K., Egele, M., Schwartz, +E. J., & Woo, M. (2018). The art, science, and engineering of +fuzzing: A survey. *arXiv*. +https://doi.org/10.48550/arXiv.1812.00140 + +*(Preprint; arXiv:1812.00140. Submitted 2018-12-01, revised 2019-04-08 +as v4. Local copy: +`docs/papers/fuzzing-art-science-engineering-survey-arxiv-1812.00140.pdf`.)* diff --git a/docs/adr/0006-admin-token-threat-intel-document-ingest.md b/docs/adr/0006-admin-token-threat-intel-document-ingest.md new file mode 100644 index 0000000..99c7048 --- /dev/null +++ b/docs/adr/0006-admin-token-threat-intel-document-ingest.md @@ -0,0 +1,96 @@ +# ADR 0006: Admin-token threat-intel document ingest + +- Status: Accepted +- Date: 2026-08-25 +- Recorded from: current `main` (`docs/architecture.md` threat + intelligence paragraph; admin console copy for the ingest routes) + +## Context + +Gateway scoring needs threat indicators and DNSBL entries. Operators +already hold documents from STIX/TAXII, MISP, and OpenCTI. Those +documents are untrusted until validated. Live pull jobs against a +MISP REST API or an OpenCTI GraphQL endpoint are a different +operational surface (credentials, scheduling, pagination) and are +**not** accepted on current `main`. + +STIX 2.1 is an OASIS Standard for exchanging cyber threat +intelligence objects (Jordan et al., 2021a). TAXII 2.1 is the OASIS +Standard for transporting STIX over HTTP collections (Jordan & +Varner, 2021). MISP is an open threat-intelligence sharing platform +and associated open standards (MISP Project, n.d.; MISP Standard, +n.d.). OpenCTI documents an open CTI platform with official +operator documentation (OpenCTI, n.d.). + +## Decision + +1. Ingest **operator-posted documents** on admin-authenticated routes: + - `POST /api/threat-intel/stix` — STIX 2.x indicator or bundle JSON + - `POST /api/threat-intel/misp` — MISP Event / attribute JSON + (`to_ids=false` attributes skipped) + - `POST /api/threat-intel/opencti` — OpenCTI observable / indicator + export JSON +2. Support operator-initiated remote TAXII ingestion at + `POST /api/threat-intel/taxii/poll`: receive a TAXII 2.1 objects URL + (or API root plus collection id) and optional credentials, fetch the + external endpoint, normalize its response to STIX, then upsert it. + That remote-fetch path remains bounded by the shared outbound policy: + absolute URLs only, no embedded credentials or fragments, HTTPS off + loopback, and no automatic redirect following while credentials are + in scope. Deeper DNS-aware egress validation remains production + hardening work until it lands on protected `main`. +3. Map supported IP, domain, URL, and hash material into + `ThreatIndicator` and `DnsblEntry` rows and update feed freshness. +4. **Live MISP REST pull** and **live OpenCTI GraphQL pull** remain + follow-ups. They are not accepted replacements for document ingest. +5. Never write TAXII or admin credentials into audit-log payloads. + +## Consequences + +- An operator (or an external poller they control) can push reviewed + intelligence without this process holding a standing MISP or + OpenCTI session. +- STIX/TAXII citations are the OASIS Standard HTML editions fetched + 2026-08-25, not drafts. +- MISP Internet-Draft HTML for a “core format” exists on + misp-standard.org; this ADR does **not** treat that draft as a + published RFC or Standards Track document. The accepted references + are the official project and standard landings. +- TAXII poll still performs an outbound HTTP GET of objects the + operator named; that is document transport, not a live MISP/OpenCTI + product puller. +- Mavroeidis and Bromander (2021) argue that CTI-sharing formats must + remain machine-readable and unambiguous to support interoperable + analysis, while Arikkat et al. (2024) emphasize provenance, + trustworthiness, and quality controls around shared CTI. Wardnet uses + that boundary to justify validation, source labeling, and the rule + that TAXII or admin credentials must never be copied into audit logs. + +## References + +Jordan, B., Piazza, R., & Darley, T. (Eds.). (2021, June 10). *STIX +Version 2.1* (OASIS Standard). OASIS Open. +https://docs.oasis-open.org/cti/stix/v2.1/os/stix-v2.1-os.html + +Jordan, B., & Varner, D. (Eds.). (2021, June 10). *TAXII Version 2.1* +(OASIS Standard). OASIS Open. +https://docs.oasis-open.org/cti/taxii/v2.1/os/taxii-v2.1-os.html + +MISP Project. (n.d.). *MISP open source threat intelligence platform +& open standards for threat intelligence sharing*. +https://www.misp-project.org/ + +MISP Standard. (n.d.). *MISP standard*. +https://www.misp-standard.org/ + +OpenCTI. (n.d.). *OpenCTI documentation*. +https://docs.opencti.io/latest/ + +Mavroeidis, V., & Bromander, S. (2021). *Cyber threat intelligence +model: An evaluation of taxonomies, sharing standards, and ontologies +within cyber threat intelligence* [Preprint]. arXiv. +https://arxiv.org/abs/2103.03530 + +Arikkat, D. R., Cihangiroglu, M., Conti, M., Rehiman K. A., R., Nicolazzo, +S., Nocera, A., & Vinod P. (2024). *SeCTIS: A framework to secure CTI +sharing* [Preprint]. arXiv. https://arxiv.org/abs/2406.14102 diff --git a/docs/adr/0007-localhost-default-bind-remote-management.md b/docs/adr/0007-localhost-default-bind-remote-management.md new file mode 100644 index 0000000..a4d0e14 --- /dev/null +++ b/docs/adr/0007-localhost-default-bind-remote-management.md @@ -0,0 +1,68 @@ +# ADR 0007: Localhost default bind; remote management requires token plus external TLS/identity + +- Status: Accepted +- Date: 2026-08-25 +- Recorded from: current `main` (`README.md` bind default and + hardening note; `docs/architecture.md` security boundaries; + `docs/security/threat-model.md` trust boundaries) + +## Context + +The management API can change routes, threat lists, and DNSBL +entries. Binding to all interfaces by default would expose that +surface on the network before TLS or identity are in place. + +`127.0.0.0/8` is the IPv4 loopback block (Cotton et al., 2013, +RFC 6890, Best Current Practice; Internet Assigned Numbers +Authority, n.d.). A default listen address of `127.0.0.1:8080` +keeps the process on that block unless an operator sets `BIND_ADDR`. + +Block mode must not flip the whole process into global enforcement +from one mistaken write. + +## Decision + +1. Default `BIND_ADDR` is **`127.0.0.1:8080`** (localhost). +2. **Remote management** is accepted only with a configured + **`ADMIN_TOKEN`** (or `ADMIN_TOKENS` / credential-registry + equivalent) **and** external TLS plus identity controls in front of + the process. This binary does not terminate public TLS or SSO by + itself. +3. **Block mode is route-scoped.** A route's `mode` applies to that + route's path prefix only. +4. Public clients enter through `/gateway/{path}`. Management writes + use `X-Admin-Token` and remain upserts. + +## Consequences + +- `cargo run` without extra config is a local lab listener, not an + internet-facing deployment. +- Current `main` does **not** yet fail closed when an operator binds to + a non-loopback address without admin credentials: the fallback + `admin_authorized` path still treats missing credentials as auth + disabled. That insecure configuration is therefore outside this + accepted deployment boundary and remains an implementation gap rather + than accepted evidence of safe remote management. +- Operators who bind to a non-loopback address must supply TLS, + identity-aware access, upstream allowlists, and rollback procedures + before production traffic (`README.md` completion baseline). +- Unauthorized management writes remain the primary control-plane + threat; token gates and audit logs are the current control, not a + substitute for SSO or mTLS (`docs/security/threat-model.md`). +- RFC 6890 is a Best Current Practice for special-purpose address + registries; it is not a WAF protocol. + +## References + +Cotton, M., Vegoda, L., Bonica, R., & Haberman, B. (2013). +*Special-purpose IP address registries* (RFC 6890). RFC Editor. +https://doi.org/10.17487/RFC6890 + +*(Best Current Practice. Documents `127.0.0.0/8` as Loopback. +Live-checked 2026-08-25 via https://www.rfc-editor.org/info/rfc6890.)* + +Internet Assigned Numbers Authority. (n.d.). *IPv4 special-purpose +address space*. +https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml + +*(Live-checked 2026-08-25: `127.0.0.0/8` named Loopback.)* diff --git a/docs/adr/0008-ai-soc-assist-advisory-human-enforcement.md b/docs/adr/0008-ai-soc-assist-advisory-human-enforcement.md new file mode 100644 index 0000000..d569c8c --- /dev/null +++ b/docs/adr/0008-ai-soc-assist-advisory-human-enforcement.md @@ -0,0 +1,73 @@ +# ADR 0008: AI SOC assist is advisory; enforcement changes require a human + +- Status: Accepted +- Date: 2026-08-25 +- Recorded from: current `main` (`docs/architecture.md` AI SOC + paragraph; `docs/security/threat-model.md` human approval boundary; + optional `/api/soc` LLM analyze path) + +## Context + +SOC operators benefit from a short triage note on a recorded event +(likely attack class, severity judgement, recommended action). That +text is easy to mistake for an automated block. + +On current `main`, optional LLM assist posts one chat-completions +request through a configured OpenAI-compatible base URL. The request +sets `orchestration_mode: "auto"`, delegating model topology and +reasoning depth to contextual-orchestrator as recorded in ADR 0010, +and returns **analysis text only**. It does not upsert routes, threats, +or DNSBL entries. + +Nelson et al. (2025) place high-impact response actions (for example +shutting down or rebuilding critical services) under leadership +decision-making and tell incident handlers to keep the ability to +**manually** select containment instead of or in addition to +automation (NIST SP 800-61r3). That is incident-handling guidance, +not a product certification. + +## Decision + +1. **AI SOC assist is advisory.** It may summarize an event, suggest + a class or severity, and recommend an action. +2. **Enforcement-changing recommendations require a human.** No LLM + output may by itself enable block mode, add a deny route, or + publish a DNSBL listing. +3. When enabled, delegate workflow depth and model selection through + the explicit adaptive orchestration contract in ADR 0010. Wardnet + retains authorization, evidence collection, and enforcement. +4. Leave the LLM backend **optional**. Current `main` exposes the + `SocLlmConfig` runtime hook, but `run_from_env` does **not** yet + wire `SOC_LLM_BASE_URL`; absent explicit in-process configuration, + assist is unavailable and the gateway still enforces + operator-written policy. +5. Do not treat cancelled scanner runs, unmerged drafts, or coverage + stubs as evidence that assist is safe to auto-enforce. + +## Consequences + +- Operators can wire contextual-orchestrator (or another compatible + endpoint) without giving that hook control-plane write authority. The + current runtime sends `orchestration_mode` but cannot prove that a generic + OpenAI-compatible endpoint honored it; such endpoints are not evidence of + ADR 0010 compliance until an acknowledgement contract is implemented. +- Adaptive orchestration changes inference execution, not Wardnet's + human enforcement boundary; see ADR 0010 for its accepted contract. +- Human approval stays required until audit trails, rollback, and + policy simulation exist for machine-proposed enforcement + (`docs/security/threat-model.md`). +- Mapping events to ATT&CK tactics is a roadmap item in + `docs/architecture.md`; it is not an accepted automated enforcer. +- NIST SP 800-61r3 supersedes SP 800-61r2; this ADR cites r3 only. + +## References + +Nelson, A., Rekhi, S., Souppaya, M., & Scarfone, K. (2025). +*Incident response recommendations and considerations for +cybersecurity risk management: A CSF 2.0 community profile* +(NIST SP 800-61r3). National Institute of Standards and Technology. +https://doi.org/10.6028/NIST.SP.800-61r3 + +*(DOI GET returned the official PDF 2026-08-25; CSRC landing +https://csrc.nist.gov/pubs/sp/800/61/r3/final also 200. Authors and +April 2025 imprint taken from that PDF front matter.)* diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 0000000..c873314 --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,58 @@ +# Architecture Decision Records + +This directory records **accepted** architecture decisions that are already +true on current `main`. It does not propose new product work. + +Narrative sources on `main`: + +- [`docs/architecture.md`](../architecture.md) — component map, security + boundaries, and adapter roadmap +- [`docs/fuzzing.md`](../fuzzing.md) — untrusted-input fuzz targets and + property-test mirror +- Repository `README.md` — operator-facing gateway, DNSBL, and workspace notes + +Each ADR is **Accepted**. Follow-ups named in an ADR (in-process Coraza +embedding, Hickory DNS authoritative serving, live MISP REST pull, live +OpenCTI GraphQL pull, a production database) are **not** accepted on `main`. + +wardnet is a standalone leaf: the binary must run by itself. Sibling +ContextualWisdomLab products (naruon, gyeot, contextual-orchestrator, +Clearfolio) are optional HTTP or contract callers, not required checkouts. + +## Series + +| ADR | Title | Status | +| --- | --- | --- | +| [0001](0001-standalone-rust-gateway-workspace-core.md) | Standalone Rust gateway with in-workspace `waf-ids-core` | Accepted | +| [0002](0002-optional-json-state-standalone-durability.md) | Optional JSON state for standalone durability | Accepted | +| [0003](0003-owasp-crs-coraza-waf-authority.md) | OWASP CRS / Coraza as WAF authority | Accepted | +| [0004](0004-rfc-5782-style-dnsbl-zone-export.md) | RFC 5782-style DNSBL zone export | Accepted | +| [0005](0005-coverage-guided-fuzzing-untrusted-inputs.md) | Coverage-guided fuzzing of untrusted-input surfaces | Accepted | +| [0006](0006-admin-token-threat-intel-document-ingest.md) | Admin-token threat-intel document ingest | Accepted | +| [0007](0007-localhost-default-bind-remote-management.md) | Localhost default bind; remote management requires token plus external TLS/identity | Accepted | +| [0008](0008-ai-soc-assist-advisory-human-enforcement.md) | AI SOC assist is advisory; enforcement changes require a human | Accepted | +| [0010](0010-adaptive-contextual-orchestrator-default.md) | SOC analysis delegates default execution to contextual-orchestrator auto | Accepted | + +## Citation policy + +References use APA 7th. Every external locator was fetched live on +2026-08-25. Informational RFCs stay labeled informational. Drafts, +unmerged pull requests, and unpublished scans are not cited as papers or +standards. Local PDF copies are attached only when redistribution is +permissible; otherwise the ADR cites, links, and summarizes the source +without vendoring the full text. + +## Template + +```markdown +# ADR NNNN: Title + +- Status: Accepted +- Date: YYYY-MM-DD +- Recorded from: current `main` (path list) + +## Context +## Decision +## Consequences +## References +``` diff --git a/docs/papers/sectis-secure-cti-sharing-arxiv-2406.14102.pdf b/docs/papers/sectis-secure-cti-sharing-arxiv-2406.14102.pdf new file mode 100644 index 0000000..0538d0b Binary files /dev/null and b/docs/papers/sectis-secure-cti-sharing-arxiv-2406.14102.pdf differ diff --git a/docs/papers/x-wad-explainable-web-anomaly-detection-arxiv-2608.27172.pdf b/docs/papers/x-wad-explainable-web-anomaly-detection-arxiv-2608.27172.pdf new file mode 100644 index 0000000..858275e Binary files /dev/null and b/docs/papers/x-wad-explainable-web-anomaly-detection-arxiv-2608.27172.pdf differ