diff --git a/.dockerignore b/.dockerignore index 06b9dea0..e10907da 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,6 +2,7 @@ target .git .github .DS_Store +wardnet-state.local.json waf-ids-state.local.json *.profraw *.profdata diff --git a/.gitignore b/.gitignore index 408e06d1..52c1a10f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /target +/wardnet-state*.json +# Temporary migration alias; remove with WAF_IDS_STATE_PATH support. /waf-ids-state*.json /runtime-state*.json diff --git a/AGENTS.md b/AGENTS.md index ae81252e..e5f20a3f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,7 @@ Cross-agent conventions for any agent (Claude, Codex, Cursor, opencode, …) wor - A failing **`trivy-fs` is a REAL finding, not a flake.** Read the job log — it prints each finding's rule id / severity / file — or the run's SARIF results, then **remediate**: - Rust dependency CVE → bump the crate (`cargo update -p `, adjust `Cargo.toml`) and commit the updated `Cargo.lock`. - Container/OS finding → fix the base image or package in the `Dockerfile`. - - k8s/IaC misconfig → fix `deploy/kubernetes/waf-ids-ai-soc.yaml` or `deploy/docker-compose.yml`. + - k8s/IaC misconfig → fix `deploy/kubernetes/wardnet.yaml` or `deploy/docker-compose.yml`. - Genuine false positive only → add a narrow, commented entry to `.trivyignore` (see the existing `AVD-KSV-0125` note for the expected style). Never broaden it to silence a real vuln. - Do **not** weaken or disable the gate. A local scan with a stale DB misses findings: run `trivy --download-db-only` first, then scan the **merge ref**, not just the PR head (e.g. `trivy fs --scanners vuln,misconfig --severity CRITICAL,HIGH --ignore-unfixed .`). - Gating is by the Security Scan **job result**, not the `code_scanning` rule. That org ruleset is intentionally **CodeQL-only** (multiple code-scanning tools can't converge on one PR ref) — do **not** add tools to it. @@ -36,7 +36,7 @@ Cross-agent conventions for any agent (Claude, Codex, Cursor, opencode, …) wor - Org rule: do **not** read config/secrets from raw environment variables (`std::env::var` / `os.getenv`) at runtime. Read them from a KV / credential registry. Org Actions secrets (e.g. `OPENAI_API_KEY`) flow **into** the KV via a bootstrap/CI step; runtime reads from the KV — env is only transport into the KV, never the runtime source. - Reference implementation: xtrmLLMBatchPython's pgcrypto-encrypted Postgres credential registry (`get_credential(name)`). Reuse that pattern (a DB-backed KV is fine) unless a dedicated KV is adopted. -- **Secrets path:** Admin tokens (`ADMIN_TOKEN` / `ADMIN_TOKENS`, optional `WAF_IDS_CREDENTIALS_PATH` JSON) bootstrap a process-local `CredentialRegistry` (`get_credential`) at startup; runtime auth reads the registry, not env. **Remaining deviation:** non-secret operational config (`BIND_ADDR`, `WAF_IDS_STATE_PATH`, `DNSBL_ORIGIN`, `EVENT_LIMIT`, `RATE_LIMIT`, …) still reads env directly — migrate those behind the same registry/KV when a durable credential store is adopted. +- **Secrets path:** Admin tokens (`ADMIN_TOKEN` / `ADMIN_TOKENS`, optional `WARDNET_CREDENTIALS_PATH` JSON) bootstrap a process-local `CredentialRegistry` (`get_credential`) at startup; runtime auth reads the registry, not env. **Remaining deviation:** non-secret operational config (`BIND_ADDR`, `WARDNET_STATE_PATH`, `DNSBL_ORIGIN`, `EVENT_LIMIT`, `RATE_LIMIT`, …) still reads env directly — migrate those behind the same registry/KV when a durable credential store is adopted. ### This repo's role in the ecosystem @@ -56,4 +56,4 @@ As of 2026-08-04, code-owner review requirements (`require_code_owner_reviews` i protection, `require_code_owner_review` in rulesets) are disabled across the ContextualWisdomLab org: there is a single maintainer (solo developer), so a code-owner approval gate can never be satisfied. This is ON HOLD until the org has multiple maintainers — do NOT re-enable these -settings or add CODEOWNERS-based merge gates before then. +settings or add CODEOWNERS-based merge gates before then. \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 742e3096..1a49cf46 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## What This Is -wardnet (crate name `waf-ids-ai-soc`) is a Rust-first WAF/IDS/AI SOC gateway and control-plane baseline for ContextualWisdomLab: web-managed API gateway routes, request scoring from threat indicators and DNSBL entries, monitor/block enforcement, RFC 5782-style DNSBL zone export, SOC event/KPI APIs, commercial readiness evidence APIs, and an embedded admin console at `/admin`. It deliberately does not reimplement a full WAF/IDS/SIEM — production coverage is meant to come from adapters to proven engines (OWASP CRS/Coraza, Suricata, STIX/TAXII, MISP/OpenCTI). +wardnet (crate name `wardnet`) is a Rust-first WAF/IDS/AI SOC gateway and control-plane baseline for ContextualWisdomLab: web-managed API gateway routes, request scoring from threat indicators and DNSBL entries, monitor/block enforcement, RFC 5782-style DNSBL zone export, SOC event/KPI APIs, commercial readiness evidence APIs, and an embedded admin console at `/admin`. It deliberately does not reimplement a full WAF/IDS/SIEM — production coverage is meant to come from adapters to proven engines (OWASP CRS/Coraza, Suricata, STIX/TAXII, MISP/OpenCTI). ## Commands @@ -23,7 +23,7 @@ Other common commands: ```bash cargo run # serve on 127.0.0.1:8080; open /admin cargo test --workspace # run a single test by name -cargo test -p waf-ids-core # test only the core crate +cargo test -p wardnet-core # test only the core crate scripts/smoke.sh # end-to-end smoke: boots the binary, exercises the API, verifies restart persistence ``` @@ -46,9 +46,9 @@ cargo +nightly fuzz run fuzz_score_request -- -max_total_time=60 Root Cargo workspace with two members (resolver 3): -- `crates/waf-ids-core` — pure domain crate, no async/HTTP deps (only `serde` + `percent-encoding`): models, validation, upserts, request scoring, DNSBL zone formatting, event retention, threat-feed freshness, KPI snapshots, commercial readiness, buyer evidence manifests. -- Root crate `waf-ids-ai-soc` (`src/lib.rs`) — Axum management API, embedded admin console, optional JSON state persistence, upstream proxying, NDJSON event export, support bundle assembly, plus the in-crate HTTP tests. Depends on `waf-ids-core`. -- `src/main.rs` — deliberately thin shim over `waf_ids_ai_soc::run_from_env` so all config/serve logic is unit-testable; covered end-to-end by `tests/binary.rs` (SIGTERM graceful shutdown). +- `crates/wardnet-core` — pure domain crate, no async/HTTP deps (only `serde` + `percent-encoding`): models, validation, upserts, request scoring, DNSBL zone formatting, event retention, threat-feed freshness, KPI snapshots, commercial readiness, buyer evidence manifests. +- Root crate `wardnet` (`src/lib.rs`) — Axum management API, embedded admin console, optional JSON state persistence, upstream proxying, NDJSON event export, support bundle assembly, plus the in-crate HTTP tests. Depends on `wardnet-core`. +- `src/main.rs` — deliberately thin shim over `wardnet::run_from_env` so all config/serve logic is unit-testable; covered end-to-end by `tests/binary.rs` (SIGTERM graceful shutdown). - `fuzz/` — a **separate** cargo workspace (empty `[workspace]` table in `fuzz/Cargo.toml` — do not remove) so root `cargo test --workspace` never builds fuzz targets. Seed corpora live in `fuzz/corpus//`. The core stays an in-repo workspace crate on purpose (no git submodule) until it has an independent release cadence. @@ -57,12 +57,24 @@ The core stays an in-repo workspace crate on purpose (no git submodule) until it - In-crate HTTP tests: `#[cfg(test)]` module in `src/lib.rs` (uses `tower::ServiceExt` to drive the Axum app). Tests that mutate env vars serialize on `ENV_GUARD`. - E2E binary test: `tests/binary.rs`. -- Property-test mirrors of the fuzz invariants (run on stable in normal CI): `tests/fuzz_invariants.rs` and `crates/waf-ids-core/tests/fuzz_invariants.rs` (proptest). +- Property-test mirrors of the fuzz invariants (run on stable in normal CI): `tests/fuzz_invariants.rs` and `crates/wardnet-core/tests/fuzz_invariants.rs` (proptest). - External smoke: `scripts/smoke.sh`. ## Runtime Configuration -Read in `run_from_env` (`src/lib.rs`): `BIND_ADDR` (default `127.0.0.1:8080`), `WAF_IDS_STATE_PATH` (optional JSON state file; omitted = seeded in-memory state), `DNSBL_ORIGIN` (default `dnsbl.local`), `EVENT_LIMIT` (default 1000, must be > 0), `RATE_LIMIT` / `RATE_LIMIT_WINDOW`, `WAF_IDS_CREDENTIALS_PATH` (optional JSON bootstrap file for process-local credentials/config), `ADMIN_TOKEN` (bootstrap transport for the shared write token), and `ADMIN_TOKENS` (bootstrap transport for comma-separated `token:actor[:role]` RBAC entries). `ADMIN_TOKEN` and `ADMIN_TOKENS` are loaded into `CredentialRegistry` before the server starts; handlers read the in-process registry/AppState copy, not raw env vars. KEV imports use the built-in CISA endpoint at runtime; only in-crate tests can override it through `AppState::with_kev_catalog_url` to point at a loopback mock server. +Read in `run_from_env` (`src/lib.rs`): `BIND_ADDR` (default +`127.0.0.1:8080`), `WARDNET_STATE_PATH` (optional JSON state file; omitted = +seeded in-memory state), `DNSBL_ORIGIN` (default `dnsbl.local`), `EVENT_LIMIT` +(default 1000, must be > 0), `RATE_LIMIT` / `RATE_LIMIT_WINDOW`, +`WARDNET_CREDENTIALS_PATH` (optional JSON bootstrap file for process-local +credentials/config; `WAF_IDS_CREDENTIALS_PATH` remains a legacy fallback), +`ADMIN_TOKEN` (bootstrap transport for the shared write token), and +`ADMIN_TOKENS` (bootstrap transport for comma-separated `token:actor[:role]` +RBAC entries). `ADMIN_TOKEN` and `ADMIN_TOKENS` are loaded into +`CredentialRegistry` before the server starts; handlers read the in-process +registry/AppState copy, not raw env vars. KEV imports use the built-in CISA +endpoint at runtime; only in-crate tests can override it through +`AppState::with_kev_catalog_url` to point at a loopback mock server. ## Key Conventions @@ -71,7 +83,9 @@ Read in `run_from_env` (`src/lib.rs`): `BIND_ADDR` (default `127.0.0.1:8080`), ` - Audit logs must never leak admin tokens (`scripts/smoke.sh` asserts this). - Untrusted-input surfaces (request scorer, state deserializer, admin-token parser, DNSBL zone export) are fuzzed; if you change one, keep its libFuzzer target and proptest mirror in sync (`docs/fuzzing.md` lists the invariants per target). - Block mode is route-scoped; default bind is localhost. See `docs/architecture.md` for security boundaries and the near-term adapter roadmap. -- Deployment assets: `Dockerfile` (two-stage build, pinned base images, runs as non-root `wafids`), `deploy/docker-compose.yml`, `deploy/kubernetes/waf-ids-ai-soc.yaml`. +- Deployment assets: `Dockerfile` (two-stage build, pinned base images, runs as + non-root `wardnet`), `deploy/docker-compose.yml`, + `deploy/kubernetes/wardnet.yaml`. ## Further Docs diff --git a/Cargo.lock b/Cargo.lock index c696190f..938d9bbd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1335,7 +1335,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] -name = "waf-ids-ai-soc" +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wardnet" version = "0.1.0" dependencies = [ "axum", @@ -1346,11 +1364,11 @@ dependencies = [ "serde_json", "tokio", "tower", - "waf-ids-core", + "wardnet-core", ] [[package]] -name = "waf-ids-core" +name = "wardnet-core" version = "0.1.0" dependencies = [ "percent-encoding", @@ -1359,24 +1377,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "wait-timeout" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" -dependencies = [ - "libc", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index b2ec231f..f5cc9b60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ [package] -name = "waf-ids-ai-soc" +name = "wardnet" version = "0.1.0" edition = "2024" description = "Rust-first WAF/IDS/AI SOC gateway with DNSBL and commercial readiness surfaces" license = "MIT" [workspace] -members = [".", "crates/waf-ids-core"] +members = [".", "crates/wardnet-core"] resolver = "3" [dependencies] @@ -16,7 +16,7 @@ futures-util = { version = "0.3", default-features = false, features = ["std"] } serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = { version = "1", features = ["fs", "macros", "net", "rt-multi-thread", "signal", "sync"] } -waf-ids-core = { path = "crates/waf-ids-core" } +wardnet-core = { path = "crates/wardnet-core" } [dev-dependencies] tower = { version = "0.5", features = ["util"] } diff --git a/Dockerfile b/Dockerfile index f92c557f..aa2a627e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,21 +13,21 @@ RUN apt-get update \ ca-certificates=20230311+deb12u1 \ curl=7.88.1-10+deb12u14 \ && rm -rf /var/lib/apt/lists/* \ - && groupadd --gid 10001 wafids \ - && useradd --uid 10001 --gid 10001 --create-home --home-dir /var/lib/waf-ids-ai-soc wafids + && groupadd --gid 10001 wardnet \ + && useradd --uid 10001 --gid 10001 --create-home --home-dir /var/lib/wardnet wardnet -COPY --from=build /app/target/release/waf-ids-ai-soc /usr/local/bin/waf-ids-ai-soc +COPY --from=build /app/target/release/wardnet /usr/local/bin/wardnet ENV BIND_ADDR=127.0.0.1:8080 \ DNSBL_ORIGIN=dnsbl.local \ EVENT_LIMIT=1000 \ - WAF_IDS_STATE_PATH=/var/lib/waf-ids-ai-soc/state.json + WARDNET_STATE_PATH=/var/lib/wardnet/state.json EXPOSE 8080 -VOLUME ["/var/lib/waf-ids-ai-soc"] -USER wafids +VOLUME ["/var/lib/wardnet"] +USER wardnet HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -fsS "http://${BIND_ADDR}/healthz" || exit 1 -ENTRYPOINT ["/usr/local/bin/waf-ids-ai-soc"] +ENTRYPOINT ["/usr/local/bin/wardnet"] diff --git a/README.md b/README.md index d1587583..8f7109cb 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# WAF IDS AI SOC +# Wardnet Rust-first gateway and SOC control-plane baseline for ContextualWisdomLab. The project starts small on purpose: - web-managed API gateway routes -- reusable `waf-ids-core` domain crate inside the same Cargo workspace +- reusable `wardnet-core` domain crate inside the same Cargo workspace - request scoring from threat indicators and DNSBL entries - monitor/block enforcement modes - RFC 5782-style DNSBL zone export @@ -21,7 +21,7 @@ It does not pretend to be a full WAF, IDS, SIEM, or SOAR yet. Production WAF and ## Completion Baseline -The program-complete baseline means the binary can run by itself, keep operator-managed routes/threats/DNSBL entries/events across restart when `WAF_IDS_STATE_PATH` is configured, enforce monitor/block decisions, export DNSBL records, and prove that loop through `scripts/smoke.sh`. +The program-complete baseline means the binary can run by itself, keep operator-managed routes/threats/DNSBL entries/events across restart when `WARDNET_STATE_PATH` is configured, enforce monitor/block decisions, export DNSBL records, and prove that loop through `scripts/smoke.sh`. It is still not a hardened internet-facing deployment. Use TLS, identity-aware access, upstream allowlists, and route rollback procedures before production traffic. @@ -66,15 +66,17 @@ Useful environment variables: - `BIND_ADDR`: listen address, default `127.0.0.1:8080` - `ADMIN_TOKEN`: optional write token for management writes via `X-Admin-Token` -- `WAF_IDS_STATE_PATH`: optional JSON state path. When omitted, the service runs with seeded in-memory state. +- `WARDNET_STATE_PATH`: optional JSON state path. When omitted, the service runs with seeded in-memory state. - `DNSBL_ORIGIN`: DNSBL zone origin, default `dnsbl.local` - `EVENT_LIMIT`: retained event count, default `1000`; must be greater than zero +Existing deployments can follow the [Wardnet rename migration](docs/migrations/wardnet-rename.md). + Example with persistent local state: ```bash ADMIN_TOKEN=dev-secret \ -WAF_IDS_STATE_PATH=./waf-ids-state.local.json \ +WARDNET_STATE_PATH=./wardnet-state.local.json \ DNSBL_ORIGIN=dnsbl.example \ cargo run ``` @@ -170,11 +172,11 @@ Deployment assets: - `Dockerfile` - `deploy/docker-compose.yml` -- `deploy/kubernetes/waf-ids-ai-soc.yaml` +- `deploy/kubernetes/wardnet.yaml` ## Workspace -- `crates/waf-ids-core`: pure domain models, validation, upserts, scoring, DNSBL zone formatting, event retention, threat-feed freshness classification, KPI snapshots, commercial readiness snapshots, and buyer evidence manifests. +- `crates/wardnet-core`: pure domain models, validation, upserts, scoring, DNSBL zone formatting, event retention, threat-feed freshness classification, KPI snapshots, commercial readiness snapshots, and buyer evidence manifests. - `src/lib.rs`: Axum management API, admin console, optional state persistence, upstream proxying, NDJSON event export, evidence manifest/support bundle assembly, and in-crate HTTP tests. - `src/main.rs`: process configuration and server startup. diff --git a/crates/waf-ids-core/Cargo.toml b/crates/wardnet-core/Cargo.toml similarity index 96% rename from crates/waf-ids-core/Cargo.toml rename to crates/wardnet-core/Cargo.toml index d229947a..d643f649 100644 --- a/crates/waf-ids-core/Cargo.toml +++ b/crates/wardnet-core/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "waf-ids-core" +name = "wardnet-core" version = "0.1.0" edition = "2024" description = "Core WAF/IDS/AI SOC domain models, scoring, DNSBL, and commercial readiness logic" diff --git a/crates/waf-ids-core/src/lib.rs b/crates/wardnet-core/src/lib.rs similarity index 98% rename from crates/waf-ids-core/src/lib.rs rename to crates/wardnet-core/src/lib.rs index f9673e0c..5e2e03f4 100644 --- a/crates/waf-ids-core/src/lib.rs +++ b/crates/wardnet-core/src/lib.rs @@ -1034,62 +1034,63 @@ pub fn kpi_snapshot_at(data: &AppData, now_unix: u64) -> SocKpiSnapshot { /// dependency — the format is a few lines of text. pub fn prometheus_exposition(kpi: &SocKpiSnapshot) -> String { let metrics: [(&str, &str, usize); 10] = [ + ("routes", "Configured gateway routes.", kpi.route_count), ( - "waf_ids_routes", - "Configured gateway routes.", - kpi.route_count, - ), - ( - "waf_ids_threat_indicators", + "threat_indicators", "Operator threat indicators loaded.", kpi.threat_indicator_count, ), ( - "waf_ids_dnsbl_entries", + "dnsbl_entries", "DNSBL reputation entries.", kpi.dnsbl_entry_count, ), ( - "waf_ids_threat_feeds", + "threat_feeds", "Imported threat feeds.", kpi.threat_feed_count, ), ( - "waf_ids_threat_feeds_fresh", + "threat_feeds_fresh", "Threat feeds within their TTL.", kpi.fresh_threat_feed_count, ), ( - "waf_ids_threat_feeds_stale", + "threat_feeds_stale", "Threat feeds past their TTL.", kpi.stale_threat_feed_count, ), ( - "waf_ids_security_events", + "security_events", "Total recorded security events.", kpi.event_count, ), ( - "waf_ids_security_events_blocked", + "security_events_blocked", "Security events with a blocked action.", kpi.blocked_event_count, ), ( - "waf_ids_security_events_monitored", + "security_events_monitored", "Security events with a monitored action.", kpi.monitor_event_count, ), ( - "waf_ids_audit_log_entries", + "audit_log_entries", "Recorded management audit-log entries.", kpi.audit_log_count, ), ]; let mut out = String::new(); - for (name, help, value) in metrics { + for (suffix, help, value) in metrics { + let name = format!("wardnet_{suffix}"); out.push_str(&format!( "# HELP {name} {help}\n# TYPE {name} gauge\n{name} {value}\n" )); + let legacy = format!("waf_ids_{suffix}"); + out.push_str(&format!( + "# HELP {legacy} Deprecated compatibility alias for {name}.\n# TYPE {legacy} gauge\n{legacy} {value}\n" + )); } out } @@ -1175,7 +1176,7 @@ pub fn commercial_readiness_snapshot_at(data: &AppData, now_unix: u64) -> Commer deployment_assets: vec![ "Dockerfile".to_string(), "deploy/docker-compose.yml".to_string(), - "deploy/kubernetes/waf-ids-ai-soc.yaml".to_string(), + "deploy/kubernetes/wardnet.yaml".to_string(), ], buyer_evidence: vec![ "docs/commercial/20b-krw-sale-readiness.md".to_string(), diff --git a/crates/waf-ids-core/tests/fuzz_invariants.rs b/crates/wardnet-core/tests/fuzz_invariants.rs similarity index 99% rename from crates/waf-ids-core/tests/fuzz_invariants.rs rename to crates/wardnet-core/tests/fuzz_invariants.rs index d2d75320..452f2513 100644 --- a/crates/waf-ids-core/tests/fuzz_invariants.rs +++ b/crates/wardnet-core/tests/fuzz_invariants.rs @@ -8,7 +8,7 @@ use proptest::prelude::*; use std::net::{IpAddr, Ipv4Addr}; -use waf_ids_core::{ +use wardnet_core::{ AppData, DnsblEntry, Severity, ThreatIndicator, export_dnsbl_zone, score_request, validate_dnsbl, }; diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index 85a02768..79d86a77 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -1,18 +1,18 @@ services: - waf-ids-ai-soc: + wardnet: build: context: .. - image: contextualwisdomlab/waf-ids-ai-soc:local + image: contextualwisdomlab/wardnet:local environment: BIND_ADDR: 0.0.0.0:8080 ADMIN_TOKEN: ${ADMIN_TOKEN:?set ADMIN_TOKEN} DNSBL_ORIGIN: ${DNSBL_ORIGIN:-dnsbl.local} EVENT_LIMIT: ${EVENT_LIMIT:-1000} - WAF_IDS_STATE_PATH: /var/lib/waf-ids-ai-soc/state.json + WARDNET_STATE_PATH: /var/lib/wardnet/state.json ports: - "8080:8080" volumes: - - waf_ids_state:/var/lib/waf-ids-ai-soc + - wardnet_state:/var/lib/wardnet healthcheck: test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/healthz"] interval: 30s @@ -21,4 +21,4 @@ services: start_period: 10s volumes: - waf_ids_state: + wardnet_state: diff --git a/deploy/kubernetes/waf-ids-ai-soc.yaml b/deploy/kubernetes/wardnet.yaml similarity index 75% rename from deploy/kubernetes/waf-ids-ai-soc.yaml rename to deploy/kubernetes/wardnet.yaml index c0988736..98fa4e4a 100644 --- a/deploy/kubernetes/waf-ids-ai-soc.yaml +++ b/deploy/kubernetes/wardnet.yaml @@ -1,19 +1,19 @@ apiVersion: v1 kind: Namespace metadata: - name: waf-ids-ai-soc + name: wardnet --- # The administrator Secret is intentionally not distributed with Wardnet. # For a fresh install, create this Namespace idempotently first, provision -# `waf-ids-ai-soc-admin` through the organization's secret-management control +# `wardnet-admin` through the organization's secret-management control # plane, wait for synchronization, then apply this complete manifest. The # Deployment has no fallback value and therefore fails closed when the Secret # or `ADMIN_TOKEN` key is absent. apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: waf-ids-ai-soc-state - namespace: waf-ids-ai-soc + name: wardnet-state + namespace: wardnet spec: accessModes: - ReadWriteOnce @@ -24,19 +24,19 @@ spec: apiVersion: apps/v1 kind: Deployment metadata: - name: waf-ids-ai-soc - namespace: waf-ids-ai-soc + name: wardnet + namespace: wardnet labels: - app.kubernetes.io/name: waf-ids-ai-soc + app.kubernetes.io/name: wardnet spec: replicas: 1 selector: matchLabels: - app.kubernetes.io/name: waf-ids-ai-soc + app.kubernetes.io/name: wardnet template: metadata: labels: - app.kubernetes.io/name: waf-ids-ai-soc + app.kubernetes.io/name: wardnet spec: automountServiceAccountToken: false securityContext: @@ -46,7 +46,7 @@ spec: type: RuntimeDefault containers: - name: gateway - image: ghcr.io/contextualwisdomlab/waf-ids-ai-soc:0.1.0 + image: ghcr.io/contextualwisdomlab/wardnet:0.1.0 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -58,17 +58,17 @@ spec: value: dnsbl.example - name: EVENT_LIMIT value: "1000" - - name: WAF_IDS_STATE_PATH - value: /var/lib/waf-ids-ai-soc/state.json + - name: WARDNET_STATE_PATH + value: /var/lib/wardnet/state.json - name: ADMIN_TOKEN valueFrom: secretKeyRef: - name: waf-ids-ai-soc-admin + name: wardnet-admin key: ADMIN_TOKEN optional: false volumeMounts: - name: state - mountPath: /var/lib/waf-ids-ai-soc + mountPath: /var/lib/wardnet readinessProbe: httpGet: path: /healthz @@ -97,16 +97,16 @@ spec: volumes: - name: state persistentVolumeClaim: - claimName: waf-ids-ai-soc-state + claimName: wardnet-state --- apiVersion: v1 kind: Service metadata: - name: waf-ids-ai-soc - namespace: waf-ids-ai-soc + name: wardnet + namespace: wardnet spec: selector: - app.kubernetes.io/name: waf-ids-ai-soc + app.kubernetes.io/name: wardnet ports: - name: http port: 80 diff --git a/docs/architecture.md b/docs/architecture.md index e1ee578b..878b0f85 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -7,7 +7,7 @@ flowchart LR operator["Security Operator"] --> admin["Admin Console"] admin --> api["Management API"] api --> app["App Crate"] - app --> core["waf-ids-core"] + app --> core["wardnet-core"] core --> state["Runtime State"] state --> file["Optional JSON State File"] client["HTTP Client"] --> gateway["Rust Gateway"] @@ -27,9 +27,9 @@ flowchart LR ## Components -- `src/main.rs`: process startup and operator configuration from `BIND_ADDR`, `ADMIN_TOKEN`, `WAF_IDS_STATE_PATH`, `DNSBL_ORIGIN`, and `EVENT_LIMIT`. +- `src/main.rs`: process startup and operator configuration from `BIND_ADDR`, `ADMIN_TOKEN`, `WARDNET_STATE_PATH`, `DNSBL_ORIGIN`, and `EVENT_LIMIT`. - `src/lib.rs`: Axum app, routing, management APIs, optional JSON persistence, gateway handler, upstream proxying, admin console, support bundle assembly, NDJSON event export, and in-crate HTTP tests. -- `crates/waf-ids-core`: reusable domain models plus validation, upsert, scoring, DNSBL zone export, event retention, threat-feed freshness, KPI snapshot, and commercial readiness logic. +- `crates/wardnet-core`: reusable domain models plus validation, upsert, scoring, DNSBL zone export, event retention, threat-feed freshness, KPI snapshot, and commercial readiness logic. - `/admin`: embedded web console. - `/gateway/{path}`: route selection, request scoring, monitor/block decision, optional upstream proxying. - `/dnsbl/zone`: DNSBL zone text using the configured origin, suitable for publication through an authoritative DNS server. @@ -59,7 +59,7 @@ flowchart LR - Default bind address is localhost. - Remote management requires `ADMIN_TOKEN` plus external TLS and identity controls. -- `WAF_IDS_STATE_PATH` enables JSON state persistence for standalone operation. Without it, the service uses seeded in-memory state. +- `WARDNET_STATE_PATH` enables JSON state persistence for standalone operation. Without it, the service uses seeded in-memory state. - File-backed writes use temporary sibling files followed by atomic rename. Management API mutations roll back in memory if the state file cannot be replaced. - Block mode is route-scoped to avoid global accidental enforcement. - JSON persistence is a baseline durability mechanism, not a substitute for a production database, backup plan, or audited change workflow. diff --git a/docs/commercial/20b-krw-sale-readiness.md b/docs/commercial/20b-krw-sale-readiness.md index 502188b4..2f8a9dd3 100644 --- a/docs/commercial/20b-krw-sale-readiness.md +++ b/docs/commercial/20b-krw-sale-readiness.md @@ -11,7 +11,7 @@ This project treats a 2B KRW sale as an enterprise due-diligence threshold, not 5. Threat feed updates must be importable through `POST /api/threat-feeds/import`. 6. The product must expose fresh/stale threat feed evidence through `GET /api/threat-feeds/freshness`. 7. The product must expose SOC event export through `GET /api/events.ndjson`. -8. The product must retain threat feed status, imported HTTP indicators, DNSBL entries, gateway routes, and security events across restart when `WAF_IDS_STATE_PATH` is configured. +8. The product must retain threat feed status, imported HTTP indicators, DNSBL entries, gateway routes, and security events across restart when `WARDNET_STATE_PATH` is configured. 9. The readiness API must report blockers instead of returning a vague success state. 10. The support bundle API must return health, KPIs, license metadata, readiness checks, feed freshness, and evidence counts without secrets. 11. The product must expose a buyer evidence manifest through `GET /api/commercial/evidence-manifest` so evaluators can verify required runtime APIs, committed documents, and deployment assets from one contract. @@ -53,4 +53,4 @@ This project treats a 2B KRW sale as an enterprise due-diligence threshold, not The project is still a commercial baseline, not a complete enterprise WAF/IDS suite. Production buyers should require follow-on integration of Coraza/OWASP CRS, Suricata EVE ingest, durable database storage, SSO/RBAC, audit logs, signed release artifacts, and production SIEM mapping before internet-edge deployment. -The current library boundary is `crates/waf-ids-core`, a local workspace crate. A submodule is not justified until an independently versioned adapter or SDK exists. +The current library boundary is `crates/wardnet-core`, a local workspace crate. A submodule is not justified until an independently versioned adapter or SDK exists. diff --git a/docs/commercial/buyer-due-diligence.md b/docs/commercial/buyer-due-diligence.md index a9402535..823f0cad 100644 --- a/docs/commercial/buyer-due-diligence.md +++ b/docs/commercial/buyer-due-diligence.md @@ -42,7 +42,7 @@ - [Dockerfile](../../Dockerfile) - [Compose stack](../../deploy/docker-compose.yml) -- [Kubernetes manifest](../../deploy/kubernetes/waf-ids-ai-soc.yaml) +- [Kubernetes manifest](../../deploy/kubernetes/wardnet.yaml) ## Buyer Lab Script diff --git a/docs/deployment/production.md b/docs/deployment/production.md index 1c46ac73..f9776bc5 100644 --- a/docs/deployment/production.md +++ b/docs/deployment/production.md @@ -5,7 +5,7 @@ Build: ```bash -docker build -t contextualwisdomlab/waf-ids-ai-soc:local . +docker build -t contextualwisdomlab/wardnet:local . ``` Run: @@ -16,8 +16,8 @@ docker run --rm \ -e BIND_ADDR=0.0.0.0:8080 \ -e ADMIN_TOKEN=replace-me \ -e DNSBL_ORIGIN=dnsbl.example \ - -v waf_ids_state:/var/lib/waf-ids-ai-soc \ - contextualwisdomlab/waf-ids-ai-soc:local + -v wardnet_state:/var/lib/wardnet \ + contextualwisdomlab/wardnet:local ``` ## Compose @@ -32,24 +32,24 @@ ADMIN_TOKEN=replace-me docker compose up --build The distributable manifest does not create an administrator Secret. A fresh cluster must create the namespace before any namespaced Secret or ExternalSecret can exist. Bootstrap the namespace idempotently first: ```bash -kubectl create namespace waf-ids-ai-soc --dry-run=client -o yaml | kubectl apply -f - +kubectl create namespace wardnet --dry-run=client -o yaml | kubectl apply -f - ``` -Then use the organization's secret-management control plane to provision an Opaque Secret named `waf-ids-ai-soc-admin` in namespace `waf-ids-ai-soc` with key `ADMIN_TOKEN`. Keep access to that Secret limited to the workload and operational identities that require it. Existing installations may run the same namespace-bootstrap command safely; it converges on the existing Namespace rather than replacing it. +Then use the organization's secret-management control plane to provision an Opaque Secret named `wardnet-admin` in namespace `wardnet` with key `ADMIN_TOKEN`. Keep access to that Secret limited to the workload and operational identities that require it. Existing installations may run the same namespace-bootstrap command safely; it converges on the existing Namespace rather than replacing it. The Deployment binds `ADMIN_TOKEN` only through that `secretKeyRef` with `optional: false`. If the Secret or key is absent, the workload does not start; there is no repository-provided fallback credential. After the external secret controller reports successful synchronization, apply the complete manifest. Its Namespace object remains in the declarative asset so later applies retain the same ownership boundary: ```bash -kubectl apply -f deploy/kubernetes/waf-ids-ai-soc.yaml +kubectl apply -f deploy/kubernetes/wardnet.yaml ``` When rotating `ADMIN_TOKEN`, wait for the updated Secret to synchronize, then restart the Deployment because environment-variable-backed Secret values are fixed when a container starts. Verify the rollout and readiness before revoking the previous token: ```bash -kubectl -n waf-ids-ai-soc rollout restart deployment/waf-ids-ai-soc -kubectl -n waf-ids-ai-soc rollout status deployment/waf-ids-ai-soc +kubectl -n wardnet rollout restart deployment/wardnet +kubectl -n wardnet rollout status deployment/wardnet ``` Failure, recovery, verification, and evidence requirements are documented in [`../doctoring/kubernetes-admin-secret-boundary.md`](../doctoring/kubernetes-admin-secret-boundary.md). diff --git a/docs/design-system.md b/docs/design-system.md index c30523ac..670fea0c 100644 --- a/docs/design-system.md +++ b/docs/design-system.md @@ -1,4 +1,4 @@ -# WAF IDS AI SOC — Design System +# Wardnet — Design System Canonical reference for the admin console UI. Tokens and components are implemented as vanilla HTML/CSS/JS embedded in the binary (`ADMIN_HTML` in `src/lib.rs`, served diff --git a/docs/figma/enterprise-product-architecture.md b/docs/figma/enterprise-product-architecture.md index a1100f20..4ac21c72 100644 --- a/docs/figma/enterprise-product-architecture.md +++ b/docs/figma/enterprise-product-architecture.md @@ -3,7 +3,7 @@ ## Artifact - FigJam: https://www.figma.com/board/JExziD87eUWKLERECUGhWQ?utm_source=codex&utm_content=edit_in_figjam&oai_id=&request_id=a97d2861-82f8-4d43-9d16-27e07b13b10c&architecture=true -- Title: WAF IDS AI SOC 2B KRW Product Architecture +- Title: Wardnet 2B KRW Product Architecture - Added section: `Freshness and SOC Export Evidence` - Added diagram: `Buyer Evidence Manifest Runtime Map` - Figma Code Connect: not used @@ -15,8 +15,8 @@ flowchart LR buyer["Enterprise Buyer Lab"] --> console["Web Admin Console"] operator["SOC Operator"] --> console console --> api["Management API"] - api --> app["waf-ids-ai-soc App Crate"] - app --> core["waf-ids-core Domain Crate"] + api --> app["wardnet App Crate"] + app --> core["wardnet-core Domain Crate"] core --> scoring["Scoring and Readiness"] core --> dnsbl["DNSBL Zone Export"] core --> kpis["SOC KPI Snapshot"] diff --git a/docs/fuzzing.md b/docs/fuzzing.md index b252299c..07e90f2f 100644 --- a/docs/fuzzing.md +++ b/docs/fuzzing.md @@ -16,10 +16,10 @@ entry points for arbitrary input. | Fuzz target | Surface (function) | Invariants | | --------------------------- | ------------------------------------------- | ---------- | -| `fuzz_score_request` | `waf_ids_core::score_request` | no panic on arbitrary path/query/body/IP; `reason` never empty; scoring deterministic | +| `fuzz_score_request` | `wardnet_core::score_request` | no panic on arbitrary path/query/body/IP; `reason` never empty; scoring deterministic | | `fuzz_appdata_json` | `serde_json::from_str::` (state file) | no panic; parsed values round-trip through serde | -| `fuzz_parse_admin_tokens` | `waf_ids_ai_soc::parse_admin_tokens` | no panic; no empty token key; no empty principal actor value | -| `fuzz_dnsbl_zone` | `waf_ids_core::export_dnsbl_zone` / `validate_dnsbl` | no panic; every TXT payload fully escaped (no zone break-out); every published A-record response code is an IPv4 loopback literal (127.0.0.0/8) | +| `fuzz_parse_admin_tokens` | `wardnet::parse_admin_tokens` | no panic; no empty token key; no empty principal actor value | +| `fuzz_dnsbl_zone` | `wardnet_core::export_dnsbl_zone` / `validate_dnsbl` | no panic; every TXT payload fully escaped (no zone break-out); every published A-record response code is an IPv4 loopback literal (127.0.0.0/8) | ## Layout @@ -30,7 +30,7 @@ fuzz/ # separate cargo workspace (isolated from the root corpus//* # committed seed corpus (attack payloads, edge cases) ``` -The property-test mirror lives in `crates/waf-ids-core/tests/fuzz_invariants.rs` +The property-test mirror lives in `crates/wardnet-core/tests/fuzz_invariants.rs` and `tests/fuzz_invariants.rs` (proptest); it enforces the same invariants on stable as part of `cargo test --workspace`. diff --git a/docs/goals/2026-07-02-initial-mvp-goal.md b/docs/goals/2026-07-02-initial-mvp-goal.md index e377c58a..2607f824 100644 --- a/docs/goals/2026-07-02-initial-mvp-goal.md +++ b/docs/goals/2026-07-02-initial-mvp-goal.md @@ -12,7 +12,7 @@ Create and publish a concrete ContextualWisdomLab WAF/IDS/AI SOC project MVP tha ## Acceptance Criteria -- Repository exists under `ContextualWisdomLab/waf-ids-ai-soc`. +- Repository exists under `ContextualWisdomLab/wardnet`. - `cargo test` passes locally and in CI. - `cargo fmt --check` passes locally and in CI. - `GET /admin` renders a management console. diff --git a/docs/migrations/wardnet-rename.md b/docs/migrations/wardnet-rename.md new file mode 100644 index 00000000..f9703c12 --- /dev/null +++ b/docs/migrations/wardnet-rename.md @@ -0,0 +1,69 @@ +# Wardnet rename + +The product, Rust packages, binary, container image, deployment resources, and +documentation now use `wardnet`. The rename changes durable deployment +identifiers as well as labels. Treat an existing installation as a data +migration, not as a fresh deployment. + +Two environment names remain as temporary startup-only compatibility aliases: + +- `WAF_IDS_STATE_PATH` falls back when `WARDNET_STATE_PATH` is unset. +- `WAF_IDS_CREDENTIALS_PATH` falls back when `WARDNET_CREDENTIALS_PATH` is unset. + +The `WARDNET_*` names take precedence when both are present. The aliases exist +only to avoid breaking an existing deployment during migration; new +configuration must use `WARDNET_*`. + +## Preserve state before first Wardnet startup + +Copy existing state before starting Wardnet. Do not start the renamed workload +against an empty destination and then copy state over it: an empty state +location can be initialized with seeded state, making it ambiguous which copy +is authoritative. Stop writes to the old workload, retain a rollback copy of +`state.json`, and verify the copied file by size and SHA-256 before starting the +new workload. Keep the old storage read-only until the renamed workload has +loaded the expected routes, threat indicators, DNSBL entries, feeds, and event +history. + +The deployment mappings are: + +| Deployment | Existing state | Wardnet state | Required cutover | +| --- | --- | --- | --- | +| Docker | `/var/lib/waf-ids-ai-soc/state.json` | `/var/lib/wardnet/state.json` | Stop the old container, copy the existing `state.json` to the new mount or volume, preserve ownership for runtime UID/GID `10001`, verify the copy, then start the Wardnet container. | +| Docker Compose | logical volume `waf_ids_state` | logical volume `wardnet_state` | Stop the old service, copy `state.json` from the old named volume into the new named volume before `docker compose up`, verify the copy, and retain the old volume for rollback. Remember that Compose may prefix the actual volume name with the project name. | +| Kubernetes | PVC `waf-ids-ai-soc-state` | PVC `wardnet-state` | Scale the old writer to zero, snapshot/clone or export/import `state.json` into storage backing `wardnet-state`, verify it before starting the new Deployment, and retain the old PVC/snapshot until validation completes. PVCs are namespaced; do not assume the new `wardnet` namespace can mount the old claim directly. | + +The environment alias alone does not migrate a container path, Compose volume, +or Kubernetes PVC. If an operator intentionally keeps the old storage instead +of copying it, the runtime path must still resolve to that storage explicitly +and the rollback plan must record that choice. + +## Migrate the Kubernetes administrator Secret before the Deployment + +The renamed manifest requires `wardnet-admin` in namespace `wardnet` and reads +its `ADMIN_TOKEN` key with `optional: false`. Existing installations commonly +have only `waf-ids-ai-soc-admin`; Kubernetes Secrets are namespaced and are not +renamed automatically. + +For an existing cluster, create the `wardnet` namespace first, then have the +organization's secret-management control plane create or synchronize +`wardnet-admin` with the required `ADMIN_TOKEN`. If the approved migration +procedure copies the value from `waf-ids-ai-soc-admin`, perform that copy +through the secret-management boundary rather than committing or echoing the +secret into repository files or shell history. Confirm that `wardnet-admin` +exists and contains the expected key before you apply `deploy/kubernetes/wardnet.yaml`. +The Deployment intentionally has no literal fallback and should remain unable +to start if the Secret is absent. + +After state and Secret migration are verified, apply `deploy/kubernetes/wardnet.yaml`, +wait for readiness, compare buyer/operator state and audit evidence with the +pre-migration snapshot, and only then retire the old workload. A failed +readiness or state comparison means roll back to the retained old +workload/storage; do not delete the old PVC, volume, or Secret as part of the +same change that first starts Wardnet. + +## Metrics compatibility + +Prometheus metrics are now emitted with the `wardnet_` prefix. The previous +`waf_ids_` series are emitted in parallel as deprecated compatibility aliases +so existing dashboards and alerts continue to work during migration. diff --git a/docs/ponytail/2026-07-02-complexity-audit.md b/docs/ponytail/2026-07-02-complexity-audit.md index 67af2edd..77f6c573 100644 --- a/docs/ponytail/2026-07-02-complexity-audit.md +++ b/docs/ponytail/2026-07-02-complexity-audit.md @@ -2,11 +2,11 @@ ## Decision -Split reusable WAF/IDS/SOC domain logic into `crates/waf-ids-core` inside the same Cargo workspace. Do not use a git submodule at this stage. +Split reusable WAF/IDS/SOC domain logic into `crates/wardnet-core` inside the same Cargo workspace. Do not use a git submodule at this stage. ## Findings -- Shrink: `src/lib.rs` mixed Axum handlers, persistence, proxying, domain models, scoring, readiness, and DNSBL formatting. Moving deterministic domain logic to `waf-ids-core` reduces the app crate surface without changing runtime behavior. +- Shrink: `src/lib.rs` mixed Axum handlers, persistence, proxying, domain models, scoring, readiness, and DNSBL formatting. Moving deterministic domain logic to `wardnet-core` reduces the app crate surface without changing runtime behavior. - YAGNI: a submodule would add versioning, CI, review, and release overhead before there is an independent library consumer. - Delete: do not create a mock "enterprise WAF engine" to justify the sale package. Keep WAF and IDS engines as explicit future adapters to Coraza/OWASP CRS and Suricata. - Keep: the single binary, JSON state option, admin console, smoke test, and deployment assets remain important for buyer lab time-to-value. @@ -14,7 +14,7 @@ Split reusable WAF/IDS/SOC domain logic into `crates/waf-ids-core` inside the sa ## Resulting Boundaries -- `crates/waf-ids-core`: pure models, validation, upserts, scoring, event retention, feed freshness, KPI snapshots, readiness snapshots, and DNSBL zone formatting. +- `crates/wardnet-core`: pure models, validation, upserts, scoring, event retention, feed freshness, KPI snapshots, readiness snapshots, and DNSBL zone formatting. - `src/lib.rs`: Axum app, admin console, management endpoints, optional persistence, upstream proxying, NDJSON event export, support bundle assembly, and integration tests. - `src/main.rs`: process configuration and server startup. diff --git a/docs/runbooks/operations.md b/docs/runbooks/operations.md index 9b6b7015..b4ddc58a 100644 --- a/docs/runbooks/operations.md +++ b/docs/runbooks/operations.md @@ -4,7 +4,7 @@ ```bash ADMIN_TOKEN=dev-secret \ -WAF_IDS_STATE_PATH=./waf-ids-state.local.json \ +WARDNET_STATE_PATH=./wardnet-state.local.json \ DNSBL_ORIGIN=dnsbl.local \ EVENT_LIMIT=1000 \ cargo run @@ -21,7 +21,7 @@ on each request. | Bootstrap transport | Variable / path | Notes | | --- | --- | --- | | Env (dev / CI) | `ADMIN_TOKEN`, `ADMIN_TOKENS` | Still supported; seeds the registry only | -| Credentials file (preferred for lab/prod packaging) | `WAF_IDS_CREDENTIALS_PATH` | JSON object with `admin_token` and/or `admin_tokens` keys; file values win per key over env | +| Credentials file (preferred for lab/prod packaging) | `WARDNET_CREDENTIALS_PATH` | JSON object with `admin_token` and/or `admin_tokens` keys; file values win per key over env | Example credentials file: @@ -45,8 +45,8 @@ Example credentials file: Token values never appear in audit log payloads. ```bash -WAF_IDS_CREDENTIALS_PATH=./credentials.local.json \ -WAF_IDS_STATE_PATH=./waf-ids-state.local.json \ +WARDNET_CREDENTIALS_PATH=./credentials.local.json \ +WARDNET_STATE_PATH=./wardnet-state.local.json \ cargo run ``` @@ -76,7 +76,7 @@ scripts/smoke.sh The smoke test starts the service on a temporary port with a temporary JSON state file, verifies admin and management surfaces, creates a blocking route, registers a commercial license, imports a threat feed, triggers a blocked gateway request, checks KPIs, readiness, support bundle, and DNSBL export, restarts the process, and verifies that route/license/feed data persisted. -When `WAF_IDS_STATE_PATH` is enabled, the process writes a temporary sibling file and atomically replaces the configured state path. If a management write cannot be persisted, the in-memory mutation is rolled back and the API returns `500`. +When `WARDNET_STATE_PATH` is enabled, the process writes a temporary sibling file and atomically replaces the configured state path. If a management write cannot be persisted, the in-memory mutation is rolled back and the API returns `500`. ## Safe Change Procedure diff --git a/docs/security/threat-model.md b/docs/security/threat-model.md index 8cf0a35b..edaaab7e 100644 --- a/docs/security/threat-model.md +++ b/docs/security/threat-model.md @@ -28,7 +28,7 @@ | Upstream SSRF through routes | Internal network exposure | Upstream scheme validation | Upstream allowlists, egress policy | | Gateway DoS | Availability loss | Rust memory safety, event retention limit | Rate limits, body limits, async event sink | | DNSBL abuse | Reputation damage | Loopback response-code validation | Authoritative DNS service, signing, publisher workflow | -| Secret disclosure | Admin compromise | Support bundle excludes admin token; secrets bootstrapped into credential registry (`WAF_IDS_CREDENTIALS_PATH` preferred over long-lived env); health exposes source label only | External secret manager / SSO, rotation, access review | +| Secret disclosure | Admin compromise | Support bundle excludes admin token; secrets bootstrapped into credential registry (`WARDNET_CREDENTIALS_PATH` preferred over long-lived env); health exposes source label only | External secret manager / SSO, rotation, access review | ## Human Approval Boundary diff --git a/docs/superpowers/plans/2026-07-02-enterprise-product-package.md b/docs/superpowers/plans/2026-07-02-enterprise-product-package.md index 6ed06d0e..c8202fb7 100644 --- a/docs/superpowers/plans/2026-07-02-enterprise-product-package.md +++ b/docs/superpowers/plans/2026-07-02-enterprise-product-package.md @@ -4,7 +4,7 @@ **Goal:** Turn the current runnable WAF/IDS/AI SOC baseline into a stronger 2B KRW enterprise product package by adding a maintainable core library boundary and committed product/design/analytics/complexity evidence. -**Architecture:** One Rust workspace. The root crate remains the web-managed gateway and deployment unit. `crates/waf-ids-core` contains deterministic domain logic that future Coraza, Suricata, MISP, TAXII, DNS, and AI SOC adapters can reuse. +**Architecture:** One Rust workspace. The root crate remains the web-managed gateway and deployment unit. `crates/wardnet-core` contains deterministic domain logic that future Coraza, Suricata, MISP, TAXII, DNS, and AI SOC adapters can reuse. **Tech Stack:** Rust 2024, Axum, Tokio, Reqwest with rustls, Serde, Cargo workspace, shell smoke test, GitHub Actions, Scorecard. @@ -16,7 +16,7 @@ - [x] Use Ponytail to decide the smallest useful complexity reduction. - [x] Use Data Analytics to define sale-readiness and SOC value metrics. - [x] Select a local workspace crate instead of a git submodule. -- [x] Add `crates/waf-ids-core` and move pure domain logic into it. +- [x] Add `crates/wardnet-core` and move pure domain logic into it. - [x] Commit Figma, Product Design, Ponytail, Data Analytics, Superpowers, README, and architecture documentation. - [x] Run full local verification: format, workspace tests, coverage gate, clippy, actionlint, smoke, and diff check. - [ ] Publish a PR and address real review/check findings. diff --git a/docs/superpowers/plans/2026-07-02-feed-freshness-siem-evidence.md b/docs/superpowers/plans/2026-07-02-feed-freshness-siem-evidence.md index ea10e355..f54ee314 100644 --- a/docs/superpowers/plans/2026-07-02-feed-freshness-siem-evidence.md +++ b/docs/superpowers/plans/2026-07-02-feed-freshness-siem-evidence.md @@ -4,7 +4,7 @@ **Goal:** Add buyer-verifiable threat-feed freshness and SOC/SIEM event export evidence to the existing 2B KRW product package. -**Architecture:** Keep one Rust workspace. Add deterministic freshness helpers to `waf-ids-core`, keep NDJSON serialization in the root app crate where `serde_json` already exists, expose both through Axum, and verify through tests and smoke. +**Architecture:** Keep one Rust workspace. Add deterministic freshness helpers to `wardnet-core`, keep NDJSON serialization in the root app crate where `serde_json` already exists, expose both through Axum, and verify through tests and smoke. **Tech Stack:** Rust 2024, Axum, Tokio, Serde, Cargo workspace, shell smoke test, GitHub Actions, FigJam. diff --git a/docs/superpowers/plans/2026-07-02-program-completion-baseline.md b/docs/superpowers/plans/2026-07-02-program-completion-baseline.md index 8ccf65ee..8b388d38 100644 --- a/docs/superpowers/plans/2026-07-02-program-completion-baseline.md +++ b/docs/superpowers/plans/2026-07-02-program-completion-baseline.md @@ -4,7 +4,7 @@ **Goal:** Upgrade the MVP into a standalone program-complete baseline with persistent state, deterministic management writes, smoke verification, and updated CI/docs. -**Architecture:** Keep the app as one Rust Axum binary. Add file-backed JSON persistence behind optional `WAF_IDS_STATE_PATH`, strengthen validators and upserts, retain gateway events with a cap, and prove the end-to-end control loop through a shell smoke test. +**Architecture:** Keep the app as one Rust Axum binary. Add file-backed JSON persistence behind optional `WARDNET_STATE_PATH`, strengthen validators and upserts, retain gateway events with a cap, and prove the end-to-end control loop through a shell smoke test. **Tech Stack:** Rust 2024, Axum 0.8, Tokio, Serde/Serde JSON, Reqwest rustls, Bash/curl for smoke verification, GitHub Actions CI. @@ -14,7 +14,7 @@ - Do not implement fake WAF/IDS engines; keep Coraza/OWASP CRS and Suricata as future real adapters. - Default bind address remains `127.0.0.1:8080`. - `ADMIN_TOKEN` protects management writes when configured. -- `WAF_IDS_STATE_PATH` is optional; absence means seeded in-memory mode. +- `WARDNET_STATE_PATH` is optional; absence means seeded in-memory mode. - CI must run `cargo fmt --check`, `cargo test --locked`, and `cargo clippy --locked -- -D warnings`. --- @@ -31,7 +31,7 @@ - Produces: `AppState::load(config: AppConfig) -> Result` - Produces: `AppState::seeded(admin_token: Option) -> AppState` for existing tests -- [x] Add environment parsing for `WAF_IDS_STATE_PATH`, `DNSBL_ORIGIN`, and `EVENT_LIMIT`. +- [x] Add environment parsing for `WARDNET_STATE_PATH`, `DNSBL_ORIGIN`, and `EVENT_LIMIT`. - [x] Serialize/deserialize `AppData`. - [x] Load state from JSON file when configured; seed and write the file when it does not exist. - [x] Persist successful management writes. diff --git a/docs/superpowers/plans/2026-07-02-waf-ids-ai-soc-mvp.md b/docs/superpowers/plans/2026-07-02-wardnet-mvp.md similarity index 96% rename from docs/superpowers/plans/2026-07-02-waf-ids-ai-soc-mvp.md rename to docs/superpowers/plans/2026-07-02-wardnet-mvp.md index 2e98d7e1..71e48d21 100644 --- a/docs/superpowers/plans/2026-07-02-waf-ids-ai-soc-mvp.md +++ b/docs/superpowers/plans/2026-07-02-wardnet-mvp.md @@ -1,4 +1,4 @@ -# WAF IDS AI SOC MVP Implementation Plan +# Wardnet MVP Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. @@ -89,5 +89,5 @@ - [x] Add CI for formatting and tests. - [x] Add Scorecard workflow and Dependabot baseline. - [x] Run final local verification. -- [x] Create `ContextualWisdomLab/waf-ids-ai-soc` if absent. +- [x] Create `ContextualWisdomLab/wardnet` if absent. - [x] Push the initial implementation to `main`. diff --git a/docs/superpowers/plans/2026-07-03-audit-log-surface.md b/docs/superpowers/plans/2026-07-03-audit-log-surface.md index 46fa3b85..531f27e8 100644 --- a/docs/superpowers/plans/2026-07-03-audit-log-surface.md +++ b/docs/superpowers/plans/2026-07-03-audit-log-surface.md @@ -4,7 +4,7 @@ **Goal:** Add buyer-verifiable management audit logs for admin write operations without storing secrets. -**Architecture:** Store audit records in `AppData` so file persistence and support-bundle export use the existing atomic state boundary. Keep audit record creation deterministic in `waf-ids-core`; keep HTTP header parsing and endpoint routing in `src/lib.rs`. +**Architecture:** Store audit records in `AppData` so file persistence and support-bundle export use the existing atomic state boundary. Keep audit record creation deterministic in `wardnet-core`; keep HTTP header parsing and endpoint routing in `src/lib.rs`. **Tech Stack:** Rust 2024, Axum 0.8, Serde, Tokio, existing JSON state persistence. @@ -15,15 +15,15 @@ - Audit logs must not persist `X-Admin-Token` or request bodies. - Audit logs must cover successful admin writes to routes, threats, DNSBL entries, commercial license metadata, and threat feed imports. - Failed authorization or validation must not create audit records. -- Audit records must survive restart when `WAF_IDS_STATE_PATH` is configured. +- Audit records must survive restart when `WARDNET_STATE_PATH` is configured. --- ### Task 1: Core Audit Model **Files:** -- Modify: `crates/waf-ids-core/src/lib.rs` -- Test: `crates/waf-ids-core/src/lib.rs` +- Modify: `crates/wardnet-core/src/lib.rs` +- Test: `crates/wardnet-core/src/lib.rs` **Interfaces:** - Produces: `AuditLogEntry { id, timestamp_unix, actor, action, resource, resource_id, outcome }` @@ -173,7 +173,7 @@ Expected: PASS. ### Task 3: Buyer Evidence And Smoke Coverage **Files:** -- Modify: `crates/waf-ids-core/src/lib.rs` +- Modify: `crates/wardnet-core/src/lib.rs` - Modify: `src/lib.rs` - Modify: `scripts/smoke.sh` - Modify: `docs/commercial/20b-krw-sale-readiness.md` diff --git a/docs/superpowers/plans/2026-07-03-buyer-evidence-manifest.md b/docs/superpowers/plans/2026-07-03-buyer-evidence-manifest.md index fd12b522..59c131c0 100644 --- a/docs/superpowers/plans/2026-07-03-buyer-evidence-manifest.md +++ b/docs/superpowers/plans/2026-07-03-buyer-evidence-manifest.md @@ -6,7 +6,7 @@ Advance the 2B KRW buyer-readiness baseline by giving enterprise evaluators one ## Scope -- Add a pure `BuyerEvidenceManifest` model and deterministic snapshot function to `crates/waf-ids-core`. +- Add a pure `BuyerEvidenceManifest` model and deterministic snapshot function to `crates/wardnet-core`. - Expose `GET /api/commercial/evidence-manifest` from the app crate. - Include the manifest in `GET /api/support-bundle` so support handoff and buyer due diligence share the same evidence map. - Add the manifest to the embedded admin console. diff --git a/docs/superpowers/specs/2026-07-02-enterprise-product-package-design.md b/docs/superpowers/specs/2026-07-02-enterprise-product-package-design.md index 11a53260..9fe0ec04 100644 --- a/docs/superpowers/specs/2026-07-02-enterprise-product-package-design.md +++ b/docs/superpowers/specs/2026-07-02-enterprise-product-package-design.md @@ -28,14 +28,14 @@ Move the current WAF/IDS/AI SOC runtime from a commercial baseline into a buyer- ## Architecture Decision -Create `crates/waf-ids-core` inside the same Cargo workspace. It owns pure domain models and deterministic logic: +Create `crates/wardnet-core` inside the same Cargo workspace. It owns pure domain models and deterministic logic: - route, threat, DNSBL, feed, event, license, KPI, and readiness models - route/threat/DNSBL/feed validation and upsert semantics - request scoring and DNSBL zone export - event retention, KPI snapshot, and readiness snapshot -The root `waf-ids-ai-soc` crate keeps process startup, Axum routes, persistence, upstream proxying, admin console, and integration tests. This boundary gives a future SDK/adapters a stable domain surface without adding submodule governance overhead. +The root `wardnet` crate keeps process startup, Axum routes, persistence, upstream proxying, admin console, and integration tests. This boundary gives a future SDK/adapters a stable domain surface without adding submodule governance overhead. ## Product Design Scope @@ -74,7 +74,7 @@ Guardrails: ## Ponytail Audit Outcome -- Shrink: move pure domain logic out of `src/lib.rs` into `crates/waf-ids-core`. +- Shrink: move pure domain logic out of `src/lib.rs` into `crates/wardnet-core`. - YAGNI: do not add a git submodule before an independent release boundary exists. - Delete: do not build a fake WAF/IDS engine; keep Coraza and Suricata as explicit future adapters. - Net: reduce app crate complexity while preserving the single-binary sales-demo path. diff --git a/docs/superpowers/specs/2026-07-02-feed-freshness-siem-evidence-design.md b/docs/superpowers/specs/2026-07-02-feed-freshness-siem-evidence-design.md index 9af26ef4..73584bbf 100644 --- a/docs/superpowers/specs/2026-07-02-feed-freshness-siem-evidence-design.md +++ b/docs/superpowers/specs/2026-07-02-feed-freshness-siem-evidence-design.md @@ -25,7 +25,7 @@ Strengthen the 2B KRW buyer-lab package with evidence that threat updates are fr Keep the existing Rust workspace boundary: -- `crates/waf-ids-core`: pure freshness classification, KPI counts, and readiness checks. +- `crates/wardnet-core`: pure freshness classification, KPI counts, and readiness checks. - `src/lib.rs`: Axum routes, NDJSON event export, support bundle assembly, admin console, and HTTP tests. - `scripts/smoke.sh`: buyer-lab verification of freshness, readiness, support bundle, and event export. diff --git a/docs/superpowers/specs/2026-07-02-program-completion-baseline-design.md b/docs/superpowers/specs/2026-07-02-program-completion-baseline-design.md index 36503c7f..977b8bc2 100644 --- a/docs/superpowers/specs/2026-07-02-program-completion-baseline-design.md +++ b/docs/superpowers/specs/2026-07-02-program-completion-baseline-design.md @@ -8,8 +8,8 @@ The previous delivery completed the published MVP: a Rust Axum gateway with web The program is complete for this baseline when all of these are true: -1. The service can load and persist routes, threat indicators, DNSBL entries, events, and the next event id through a JSON state file configured by `WAF_IDS_STATE_PATH`. -2. If `WAF_IDS_STATE_PATH` is absent, the service still runs in seeded in-memory mode for demos and tests. +1. The service can load and persist routes, threat indicators, DNSBL entries, events, and the next event id through a JSON state file configured by `WARDNET_STATE_PATH`. +2. If `WARDNET_STATE_PATH` is absent, the service still runs in seeded in-memory mode for demos and tests. 3. The health endpoint reports persistence mode, DNSBL origin, and event retention settings. 4. Management writes require `ADMIN_TOKEN` when configured, validate records, upsert deterministic records, and persist successful changes before returning. 5. Gateway events are retained with a configurable cap and persisted when file-backed state is enabled. diff --git a/docs/superpowers/specs/2026-07-02-waf-ids-ai-soc-design.md b/docs/superpowers/specs/2026-07-02-wardnet-design.md similarity index 98% rename from docs/superpowers/specs/2026-07-02-waf-ids-ai-soc-design.md rename to docs/superpowers/specs/2026-07-02-wardnet-design.md index 1759ac16..e7d8bafb 100644 --- a/docs/superpowers/specs/2026-07-02-waf-ids-ai-soc-design.md +++ b/docs/superpowers/specs/2026-07-02-wardnet-design.md @@ -1,4 +1,4 @@ -# WAF IDS AI SOC Design +# Wardnet Design ## Objective diff --git a/docs/superpowers/specs/2026-07-03-buyer-evidence-manifest-design.md b/docs/superpowers/specs/2026-07-03-buyer-evidence-manifest-design.md index c6fde1a0..39aa23bb 100644 --- a/docs/superpowers/specs/2026-07-03-buyer-evidence-manifest-design.md +++ b/docs/superpowers/specs/2026-07-03-buyer-evidence-manifest-design.md @@ -6,7 +6,7 @@ The runtime already exposes commercial readiness, feed freshness, SOC NDJSON exp ## Design -Keep the evidence manifest in `waf-ids-core` because it is deterministic domain evidence assembled from existing `AppData`, KPI, and readiness snapshots. +Keep the evidence manifest in `wardnet-core` because it is deterministic domain evidence assembled from existing `AppData`, KPI, and readiness snapshots. The app crate remains responsible only for: diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index efa8fb36..772c04df 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -1,4 +1,4 @@ -# Coverage-guided fuzzing harness for waf-ids-ai-soc. +# Coverage-guided fuzzing harness for wardnet. # # This is a SEPARATE workspace (note the empty `[workspace]` table below) so it # is excluded from the root workspace. `cargo build`/`cargo test --workspace` @@ -10,7 +10,7 @@ # - libfuzzer-sys MIT OR Apache-2.0 OR NCSA # - arbitrary MIT OR Apache-2.0 [package] -name = "waf-ids-fuzz" +name = "wardnet-fuzz" version = "0.0.0" publish = false edition = "2021" @@ -22,8 +22,8 @@ cargo-fuzz = true libfuzzer-sys = "0.4" arbitrary = { version = "1", features = ["derive"] } serde_json = "1" -waf-ids-core = { path = "../crates/waf-ids-core" } -waf-ids-ai-soc = { path = ".." } +wardnet-core = { path = "../crates/wardnet-core" } +wardnet = { path = ".." } [[bin]] name = "fuzz_score_request" diff --git a/fuzz/fuzz_targets/fuzz_appdata_json.rs b/fuzz/fuzz_targets/fuzz_appdata_json.rs index 0abaacb8..7c21f65a 100644 --- a/fuzz/fuzz_targets/fuzz_appdata_json.rs +++ b/fuzz/fuzz_targets/fuzz_appdata_json.rs @@ -8,7 +8,7 @@ //! any value that deserializes must round-trip back through serde_json. use libfuzzer_sys::fuzz_target; -use waf_ids_core::AppData; +use wardnet_core::AppData; fuzz_target!(|data: &[u8]| { let Ok(text) = std::str::from_utf8(data) else { diff --git a/fuzz/fuzz_targets/fuzz_dnsbl_zone.rs b/fuzz/fuzz_targets/fuzz_dnsbl_zone.rs index 4cf0937f..829486f0 100644 --- a/fuzz/fuzz_targets/fuzz_dnsbl_zone.rs +++ b/fuzz/fuzz_targets/fuzz_dnsbl_zone.rs @@ -14,7 +14,7 @@ use arbitrary::Arbitrary; use libfuzzer_sys::fuzz_target; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; -use waf_ids_core::{export_dnsbl_zone, validate_dnsbl, DnsblEntry}; +use wardnet_core::{export_dnsbl_zone, validate_dnsbl, DnsblEntry}; /// A response code drawn from the raw fuzz bytes: arbitrary strings plus real IP /// literals (loopback, non-loopback IPv4, IPv6) so the zone A-record invariant diff --git a/fuzz/fuzz_targets/fuzz_parse_admin_tokens.rs b/fuzz/fuzz_targets/fuzz_parse_admin_tokens.rs index 80fadda8..6989b0d9 100644 --- a/fuzz/fuzz_targets/fuzz_parse_admin_tokens.rs +++ b/fuzz/fuzz_targets/fuzz_parse_admin_tokens.rs @@ -1,5 +1,5 @@ #![no_main] -//! Fuzz the admin-token config parser: `waf_ids_ai_soc::parse_admin_tokens`. +//! Fuzz the admin-token config parser: `wardnet::parse_admin_tokens`. //! //! This parses the `ADMIN_TOKENS` operator config string //! (`token:actor[:role],...`) into an RBAC principal map. Malformed or @@ -9,7 +9,7 @@ //! * every actor value is non-empty (defaults to "admin"). use libfuzzer_sys::fuzz_target; -use waf_ids_ai_soc::parse_admin_tokens; +use wardnet::parse_admin_tokens; fuzz_target!(|data: &[u8]| { let Ok(raw) = std::str::from_utf8(data) else { diff --git a/fuzz/fuzz_targets/fuzz_score_request.rs b/fuzz/fuzz_targets/fuzz_score_request.rs index ea75f48b..c7119e9c 100644 --- a/fuzz/fuzz_targets/fuzz_score_request.rs +++ b/fuzz/fuzz_targets/fuzz_score_request.rs @@ -1,5 +1,5 @@ #![no_main] -//! Fuzz the core WAF request scorer: `waf_ids_core::score_request`. +//! Fuzz the core WAF request scorer: `wardnet_core::score_request`. //! //! This is the primary untrusted-input surface (surfaced via CodeGraph: //! `codegraph_explore "score_request anomaly_signal normalize decode ..."`). @@ -16,7 +16,7 @@ use arbitrary::Arbitrary; use libfuzzer_sys::fuzz_target; use std::net::{IpAddr, Ipv4Addr}; -use waf_ids_core::{score_request, DnsblEntry, Severity, ThreatIndicator}; +use wardnet_core::{score_request, DnsblEntry, Severity, ThreatIndicator}; #[derive(Arbitrary, Debug)] struct Indicator { diff --git a/scripts/smoke.sh b/scripts/smoke.sh index 5df0c730..c1eff7fc 100755 --- a/scripts/smoke.sh +++ b/scripts/smoke.sh @@ -31,7 +31,7 @@ start_server() { cd "$ROOT_DIR" BIND_ADDR="127.0.0.1:$PORT" \ ADMIN_TOKEN="$ADMIN_TOKEN_VALUE" \ - WAF_IDS_STATE_PATH="$STATE_FILE" \ + WARDNET_STATE_PATH="$STATE_FILE" \ DNSBL_ORIGIN="dnsbl.test" \ EVENT_LIMIT="5" \ cargo run --quiet @@ -78,7 +78,7 @@ assert_json_field "$health" 'data["persistence"] == "file"' assert_json_field "$health" 'data["dnsbl_origin"] == "dnsbl.test"' assert_json_field "$health" 'data["event_limit"] == 5' -curl -fsS "$BASE_URL/admin" | grep -q "ContextualWisdomLab WAF/IDS/AI SOC Gateway" +curl -fsS "$BASE_URL/admin" | grep -q "

Wardnet

" unauthorized_code="$( curl -sS -o /dev/null -w '%{http_code}' \ diff --git a/src/credentials.rs b/src/credentials.rs index bcc07e50..6470193d 100644 --- a/src/credentials.rs +++ b/src/credentials.rs @@ -17,7 +17,7 @@ pub const CRED_ADMIN_TOKENS: &str = "admin_tokens"; #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)] #[serde(rename_all = "snake_case")] pub enum CredentialSource { - /// At least one secret came from `WAF_IDS_CREDENTIALS_PATH`. + /// At least one secret came from `WARDNET_CREDENTIALS_PATH`. File, /// Secrets came only from env bootstrap (`ADMIN_TOKEN` / `ADMIN_TOKENS`). Env, diff --git a/src/kev_import.rs b/src/kev_import.rs index 68755e2b..a5c27cc2 100644 --- a/src/kev_import.rs +++ b/src/kev_import.rs @@ -7,10 +7,10 @@ //! //! The catalog is CVE-centric: entries carry no IP/domain/URL/hash //! observable, so `dnsbl` stays empty. It is kept on [`KevImportMaterial`] -//! only for parity with the shared [`waf_ids_core::ThreatFeedImport`] shape +//! only for parity with the shared [`wardnet_core::ThreatFeedImport`] shape //! every adapter in this family produces. -use waf_ids_core::{DnsblEntry, Severity, ThreatIndicator}; +use wardnet_core::{DnsblEntry, Severity, ThreatIndicator}; /// Parsed KEV import ready for the existing threat-feed upsert path. #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/src/lib.rs b/src/lib.rs index ab902cae..8befd927 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,7 @@ use tokio::{ fs, sync::{Mutex, RwLock}, }; -use waf_ids_core::{ +use wardnet_core::{ AppData, BLOCK_SCORE, buyer_evidence_manifest_at, commercial_readiness_snapshot_at, enforce_event_limit, kpi_snapshot_at, prometheus_exposition, rate_limit_step, record_audit_log, replace_threat_feed_ownership, select_route, signature_catalog, threat_feed_freshness_snapshot, @@ -27,7 +27,7 @@ use waf_ids_core::{ validate_commercial_profile, validate_dnsbl, validate_route, validate_threat, validate_threat_feed_import, }; -pub use waf_ids_core::{ +pub use wardnet_core::{ AuditLogEntry, BuyerEvidenceEndpoint, BuyerEvidenceManifest, BuyerEvidenceRuntimeCounts, CommercialProfile, CommercialReadiness, DnsblEntry, EnforcementMode, LicenseStatus, NewAuditLogEntry, ProductEdition, ReadinessCheck, ReadinessStatus, RouteConfig, ScoredRequest, @@ -569,7 +569,7 @@ fn clearfolio_tenant_headers(config: &ClearfolioConfig) -> [(&'static str, &str) ] } -/// Renders a waf-ids document to plain-text bytes for Clearfolio ingest. +/// Renders a Wardnet document to plain-text bytes for Clearfolio ingest. /// Clearfolio only blocks `hwp`/`hwpx`, so text uploads convert normally. /// Returns `(filename, bytes)` or `None` for an unknown kind. fn clearfolio_document(kind: &str, data: &AppData) -> Option<(String, Vec)> { @@ -613,7 +613,7 @@ async fn clearfolio_config(State(state): State) -> Json, @@ -2906,7 +2906,7 @@ const ADMIN_HTML: &str = r##" -WAF IDS AI SOC — Console +Wardnet — Console