Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
f821534
test(reputation): add contract crate workspace
seonghobae Sep 6, 2026
4681872
test(reputation): scaffold contract crate
seonghobae Sep 6, 2026
7b3b297
test(reputation): expose contract model module
seonghobae Sep 6, 2026
4cf6e93
test(reputation): add deliberately permissive v1 contract stub
seonghobae Sep 6, 2026
6959689
test(reputation): add synthetic exact-host contract fixture
seonghobae Sep 6, 2026
1eff7d2
test(reputation): add hostile v1 contract RED
seonghobae Sep 6, 2026
21c2b9c
test(reputation): lock contract workspace
seonghobae Sep 6, 2026
b912182
fix(reputation): restore generated lock integrity
seonghobae Sep 6, 2026
d8c9165
chore(reputation): bootstrap generated lock artifact
seonghobae Sep 6, 2026
00cb63e
ci(reputation): materialize formatted bootstrap output
seonghobae Sep 6, 2026
c1c8c52
ci(reputation): preserve existing dependency lock
seonghobae Sep 6, 2026
48dff58
test(reputation): reach semantic contract RED
seonghobae Sep 6, 2026
75f5a45
ci(reputation): execute semantic RED on alternate hosted pool
seonghobae Sep 6, 2026
880fc7b
fix(reputation): fail closed on invalid v1 contracts
seonghobae Sep 6, 2026
3e6bead
style(reputation): apply rustfmt to contract validator
seonghobae Sep 6, 2026
0254533
ci(reputation): remove completed semantic rescue lane
seonghobae Sep 6, 2026
87d390c
test(reputation): bind decisions to request and evidence identity
seonghobae Sep 6, 2026
f7f6a9d
ci(reputation): execute decision-binding RED on hosted macOS
seonghobae Sep 6, 2026
9a07c7a
style(reputation): format decision-binding RED
seonghobae Sep 6, 2026
64ea63b
style(reputation): apply exact rustfmt to binding RED
seonghobae Sep 6, 2026
0cea14e
fix(reputation): bind decisions to context and evidence generation
seonghobae Sep 6, 2026
42b26ea
ci(reputation): retire completed decision-binding rescue
seonghobae Sep 6, 2026
23d2b3f
test(reputation): require provenance for enforcement evidence
seonghobae Sep 6, 2026
7e058de
ci(reputation): execute provenance RED on hosted macOS
seonghobae Sep 6, 2026
8577085
ci(reputation): bind provenance RED to exact source head
seonghobae Sep 6, 2026
71086b1
fix(reputation): reject untraceable enforcement evidence
seonghobae Sep 6, 2026
f549c3d
ci(reputation): retire completed provenance rescue
seonghobae Sep 6, 2026
c069999
test(reputation): reject untraceable adverse decisions
seonghobae Sep 6, 2026
3d83ec7
ci(reputation): execute adverse-evidence RED on hosted macOS
seonghobae Sep 6, 2026
ba962a1
test(reputation): make adverse-evidence RED executable
seonghobae Sep 6, 2026
ef8fed6
fix(reputation): reject untraceable adverse decisions
seonghobae Sep 6, 2026
5629290
ci(reputation): retire adverse-evidence rescue
seonghobae Sep 6, 2026
f686821
test(reputation): forbid known-malicious allow decisions
seonghobae Sep 6, 2026
7e33ee8
ci(reputation): execute action-consistency RED on hosted macOS
seonghobae Sep 6, 2026
94c0dde
fix(reputation): fail closed on adverse allow actions
seonghobae Sep 6, 2026
d34cc92
ci(reputation): retire completed action-consistency rescue
seonghobae Sep 6, 2026
913cf4e
test(reputation): reject unavailable-authority allow
seonghobae Sep 6, 2026
414fb98
fix(reputation): fail closed on unhealthy authority allow
seonghobae Sep 6, 2026
c83149c
test(reputation): reject contradictory decision reasons
seonghobae Sep 6, 2026
ebf1dbb
ci(reputation): verify contradictory reason RED and causal fix
seonghobae Sep 6, 2026
92b7c04
fix(reputation): bind decision reason to assessment
seonghobae Sep 6, 2026
28e4bf3
ci(reputation): remove completed reason repair harness
seonghobae Sep 6, 2026
f1ebc06
test(reputation): preserve authority-failure precedence
seonghobae Sep 6, 2026
f1e0950
test(reputation): execute authority-precedence RED
seonghobae Sep 6, 2026
e040201
fix(reputation): preserve authority-failure reason precedence
seonghobae Sep 6, 2026
2e8f90b
ci(reputation): verify authority-precedence causal fix
seonghobae Sep 6, 2026
8e75415
test(reputation): reject denial reasons on allow envelopes
seonghobae Sep 6, 2026
e31f840
test(reputation): execute denial-reason RED
seonghobae Sep 6, 2026
990410e
fix(reputation): bind allow actions to business authorization
seonghobae Sep 6, 2026
94dc113
test(reputation): cover authorized unknown decision mapping
seonghobae Sep 6, 2026
afbbd99
ci(reputation): verify decision mapping repair
seonghobae Sep 6, 2026
f89c222
ci(reputation): remove completed decision verification workflow
seonghobae Sep 6, 2026
73a20dd
test(reputation): pin fail-closed decision error precedence
seonghobae Sep 6, 2026
dbb91e7
ci(reputation): execute error-precedence RED on exact source
seonghobae Sep 6, 2026
68df34b
test(reputation): pin provenance validation error
seonghobae Sep 6, 2026
62d17b9
docs(reputation): trace contract evidence rationale
seonghobae Sep 6, 2026
a5a4a01
docs(reputation): link contract traceability from crate
seonghobae Sep 6, 2026
71cf87b
docs(reputation): complete production contract rustdoc
seonghobae Sep 6, 2026
ffc5db2
fix(reputation): preserve fail-closed error precedence
seonghobae Sep 6, 2026
729c221
test(reputation): reject scope-widening unknown evidence fields
seonghobae Sep 6, 2026
c9ee13b
fix(reputation): reject unknown wire-contract fields
seonghobae Sep 6, 2026
9994948
docs(reputation): trace fail-closed wire validation
seonghobae Sep 6, 2026
4f5a9dd
test(reputation): cover strict v1 wire structs
seonghobae Sep 6, 2026
a7e1bbd
test(reputation): reject unknown decision fields
seonghobae Sep 6, 2026
305308a
style(reputation): keep contract test imports rustfmt-stable
seonghobae Sep 6, 2026
d4b84d8
style(reputation): normalize serde test imports
seonghobae Sep 6, 2026
c9a0237
test(reputation): require explicit tenant source eligibility
seonghobae Sep 6, 2026
1f97070
fix(reputation): bind reviewed sources to explicit tenant eligibility
seonghobae Sep 6, 2026
52fbb80
test(reputation): cover tenant eligibility invariants
seonghobae Sep 6, 2026
8121000
test(reputation): bind fixture source to tenant scope
seonghobae Sep 6, 2026
cba547d
docs(reputation): trace tenant eligibility fail-closed boundary
seonghobae Sep 6, 2026
45f2aec
style(reputation): apply rustfmt to contract core
seonghobae Sep 6, 2026
dd5a82d
test(reputation): expose observable URL contract limit drift
seonghobae Sep 6, 2026
0282c9d
ci(reputation): add bounded observable URL repair
seonghobae Sep 6, 2026
2f7d504
fix(reputation): honor observable URL v1 bound
seonghobae Sep 6, 2026
96ddd7f
ci(reputation): coalesce superseded verifier runs
seonghobae Sep 6, 2026
01270cf
test(reputation): enforce decision evidence reference bound
seonghobae Sep 7, 2026
47f3683
ci(reputation): prove evidence reference limit RED
seonghobae Sep 7, 2026
a480d94
ci(reputation): add bounded evidence-ref repair
seonghobae Sep 7, 2026
53caa42
fix(ci): remove unsafe PR-head repair workflow
seonghobae Sep 7, 2026
2b9e926
fix(reputation): bound decision evidence references
seonghobae Sep 7, 2026
79b89c0
ci(reputation): use supported macOS runner label
seonghobae Sep 7, 2026
1a86843
ci(reputation): route evidence verifier to supported macOS label
seonghobae Sep 7, 2026
5a8a13c
ci(reputation): remove completed precedence verifier
seonghobae Sep 7, 2026
9de0ea5
ci(reputation): remove completed evidence-limit verifier
seonghobae Sep 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description = "Rust-first WAF/IDS/AI SOC gateway with DNSBL and commercial readi
license = "MIT"

[workspace]
members = [".", "crates/waf-ids-core"]
members = [".", "crates/waf-ids-core", "crates/wardnet-reputation-core"]
resolver = "3"

[dependencies]
Expand Down
12 changes: 12 additions & 0 deletions crates/wardnet-reputation-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "wardnet-reputation-core"
version = "0.1.0"
edition = "2024"
description = "Pure Wardnet outbound site-reputation domain contracts and policy core"
license = "MIT"

[dependencies]
serde = { version = "1", features = ["derive"] }

[dev-dependencies]
serde_json = "1"
49 changes: 49 additions & 0 deletions crates/wardnet-reputation-core/TRACEABILITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Reputation contract research and standards traceability

This note records the evidence boundary for `wardnet-reputation-core`. The crate defines transport-neutral Wardnet domain contracts; it is not an anomaly detector, feed client, executable egress authority, or transport policy engine.

## Decision rationale

NIST Cybersecurity Framework (CSF) 2.0 treats Detect as outcomes for finding and analyzing possible cybersecurity attacks and compromises while leaving implementation mechanisms to the adopting organization. Wardnet therefore keeps the observed security assessment, evidence-authority health, and policy action as separate fields instead of treating a detector output as self-executing authorization.

Chandola, Banerjee, and Kumar (2009) show that anomaly-detection techniques depend on domain-specific assumptions about what distinguishes normal from anomalous behavior. That supports a conservative contract boundary here: absence of eligible adverse evidence is `unknown`, not evidence of benignness; producer confidence is retained as producer metadata rather than converted into a Wardnet probability; and an adverse classification remains traceable to reviewed evidence. The paper does **not** define Wardnet's `KnownMalicious`, `Suspicious`, or `Unknown` vocabulary. Those are Wardnet bounded-context terms for evidence state and must not be presented as categories from the paper.

The v1 contract therefore chooses:

- `KnownMalicious` only for eligible reviewed evidence that asserts a hard threat within explicit scope;
- `Suspicious` for adverse evidence that does not establish the hard-threat condition;
- `Unknown` when no eligible adverse match establishes safety;
- a separate `EvidenceHealthV1` so source outage or expiry can fail closed without rewriting the underlying assessment;
- a separate `PolicyActionV1`, because a Wardnet reputation allow only permits continuation to independent gates and is never executable EgressWeave transport authorization.

Rejected alternatives are: treating `unknown` as benign, aggregating producer confidence into an invented probability, using HTTP success as an authorization signal, or allowing business authorization to override adverse evidence. These choices would erase provenance or conflate observation, policy, and enforcement authority.

Load-balancing literature is intentionally not used to justify this contract shape. This crate performs no scheduling, dispatch, network I/O, or executable load balancing, so latency/implementation-overhead results from load-balancing systems are not causal evidence for the v1 data model. Performance and concurrency research becomes applicable when the evaluator/cache and measured deployment path are implemented; the implementation plan requires those later slices to profile and benchmark the real path rather than pre-justify this transport-neutral schema with unrelated systems results.

## Wire-schema compatibility and fail-closed decoding

The v1 wire structs accept only fields declared by the exact `wardnet.reputation.v1` schema. Serde's default forward-compatible behavior of ignoring unknown struct fields is deliberately rejected at this security boundary. An unrecognized scope-bearing field can otherwise combine with an omitted optional field and change semantics. The hostile regression demonstrates the concrete case: `tenant_ids` would be ignored while absent `tenant_id` deserializes as `None`, and `None` is the contract state that may represent globally applicable evidence. That is a scope-widening failure, not harmless extension data.

The same rule applies to reviewed source eligibility. A source policy must now state whether it is reviewed for `all_authenticated_tenants` or an `explicit_tenant_set`; an omitted tenant-scope declaration is invalid, an explicit set cannot be empty, and an all-tenant declaration cannot smuggle a contradictory tenant list. This closes the gap between authenticated tenant binding and source eligibility without treating a missing restriction as an implicit organization-wide grant. It also keeps the tenant decision inside Wardnet's reputation-policy contract rather than moving identity authentication into this crate.

MITRE CWE-20 explicitly calls out missing and extra inputs as properties that input validation should consider and recommends accepting only values that strictly conform to the intended specification. NIST SP 800-218 SSDF 1.1 PW.5.1 likewise includes validating all inputs as a secure-coding implementation example. Accordingly, every v1 wire struct uses strict unknown-field rejection. A producer or consumer that needs a new security-relevant field must negotiate a new compatible schema version instead of relying on a v1 reader to discard it.

The rejected alternative was permissive unknown-field decoding for forward compatibility. It was rejected because this contract contains optional scope, marking, and evidence metadata whose absence has domain meaning; silently discarding a misspelled or future field can therefore convert an explicit restriction into absence. Exact versioning is the safer and more reviewable compatibility mechanism.

As of 2026-09-06, NIST SP 800-218 Rev. 1 / SSDF 1.2 is still an Initial Public Draft rather than a final replacement. It is tracked for forward awareness, while the final SSDF 1.1 remains the normative NIST citation used for this implemented decision.

## Source handling

The ACM article is cited by DOI and bibliographic metadata only. Its publisher access is not assumed to grant redistribution rights, so no article PDF is copied into this repository. NIST CSF 2.0 and SSDF 1.1 are linked to official NIST publications. Future local copies must be added only when redistribution terms are verified.

## References

Chandola, V., Banerjee, A., & Kumar, V. (2009). Anomaly detection: A survey. *ACM Computing Surveys, 41*(3), Article 15. https://doi.org/10.1145/1541880.1541882

MITRE. (n.d.). *CWE-20: Improper input validation* (Version 4.20). Retrieved September 6, 2026, from https://cwe.mitre.org/data/definitions/20.html

Pascoe, C., Quinn, S., & Scarfone, K. (2024). *The NIST Cybersecurity Framework (CSF) 2.0* (NIST CSWP 29). National Institute of Standards and Technology. https://doi.org/10.6028/NIST.CSWP.29

Souppaya, M., & Scarfone, K. (2022). *Secure Software Development Framework (SSDF) version 1.1: Recommendations for mitigating the risk of software vulnerabilities* (NIST SP 800-218). National Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-218

Booth, H., Ogata, M., Kent, K., Souppaya, M., & Dodson, D. (2025). *Secure Software Development Framework (SSDF) version 1.2: Recommendations for mitigating the risk of software vulnerabilities* (NIST SP 800-218 Rev. 1, Initial Public Draft). National Institute of Standards and Technology. https://csrc.nist.gov/pubs/sp/800/218/r1/ipd
12 changes: 12 additions & 0 deletions crates/wardnet-reputation-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//! Pure Wardnet outbound site-reputation contracts.
//!
//! This crate deliberately performs no HTTP, DNS, transport authorization, database I/O,
//! environment access, or LLM work. Executable outbound target interpretation remains an
//! EgressWeave responsibility; this crate only accepts already-canonical offline descriptors.
//!
//! The research, standards, rejected alternatives, and evidence-handling rationale for this
//! contract boundary are recorded in the adjacent [TRACEABILITY.md](../TRACEABILITY.md).

pub mod model;

pub use model::*;
Loading
Loading