cidr-audit

    Audit IPv4 CIDR allow/deny rules for overlap, shadowing, and risky network ranges in pure MoonBit

    cidr
    ipv4
    network
    audit
    security
    Download zip
    Author
    Version
    0.1.2
    License
    Apache-2.0
    Last updated
    21 days ago
    Downloads
    17

    #MoonCIDR Audit

    MoonCIDR Audit is a pure MoonBit library for auditing ordered IPv4/CIDR allow and deny rules. It helps gateway, reverse proxy, cloud security group, and operations configuration authors find rule shadowing, dangerous wide ranges, non-canonical CIDR input, duplicate rules, and risky special address spaces.

    The project is intentionally small in scope: it does not try to be a firewall, packet filter, or network daemon. It focuses on the reusable analysis layer that other MoonBit tools can build on.

    #Features

    • Parse IPv4 addresses and CIDR blocks without external dependencies.
    • Normalize CIDR blocks such as 192.168.1.99/24 to 192.168.1.0/24.
    • Evaluate ordered allow and deny rules.
    • Detect duplicate rules, shadowed rules, conflicting overlaps, redundant overlaps, global deny rules, and very wide allow rules.
    • Classify private, loopback, link-local, multicast, unspecified, and broadcast address ranges.
    • Provide strict, gateway, and quiet audit policies.
    • Produce plain text, Markdown table, and JSON-like reports.
    • Explain why a probe IP matches a rule.
    • Compare two rule sets and summarize risky changes.
    • Produce remediation hints for common findings.
    • Merge overlapping or adjacent address ranges and find coverage holes.
    • Deduplicate contained CIDRs and recursively aggregate sibling networks.
    • Import native rules, Nginx allow/deny directives, and CSV rule lists.
    • Apply configurable CI deployment gates to audit reports.

    #Quick Start

    Run the main demo:

    moon run ./cmd/main

    Run example scenarios:

    moon run ./examples/gateway moon run ./examples/cloud

    The main demo now walks through auditing, probe decisions, detailed explanations, a release gate, coverage holes, CIDR aggregation, and Nginx configuration import.

    Run checks:

    moon check moon build --target all moon test --target all --deny-warn

    #Basic Usage

    let ruleset = @cidr.parse_rules([
    "allow 10.0.0.0/8 internal network",
    "deny 10.1.2.0/24 blocked subnet",
    "allow 192.168.1.99/24 host bits will be normalized",
    "deny 0.0.0.0/0 default deny",
    ])

    let report = ruleset.audit()
    println(report.text_report())

    let ip = @cidr.IPv4::parse("10.1.2.9").unwrap()
    println(ruleset.decide(ip).summary())

    #Example Findings

    MoonCIDR Audit can report findings like:

    [critical] too_wide_allow R1: allow rule covers a very wide network: 10.0.0.0/8 [critical] shadowed_rule R2 related=R1: rule is already covered by earlier allow rule R1 [info] non_canonical_cidr R3: input 192.168.1.99/24 was normalized to 192.168.1.0/24 [critical] global_deny R4: deny rule blocks the entire IPv4 space

    #API Overview

    Important types:

    • IPv4: parsed IPv4 address stored as UInt.
    • CidrBlock: normalized IPv4 CIDR block.
    • RuleAction: Allow or Deny.
    • Rule: ordered rule with id, action, block, source block, and note.
    • RuleSet: parsed rule collection with decision and audit helpers.
    • AuditPolicy: strict, gateway, and quiet policy presets.
    • AuditReport: findings, severity counts, risk score, and report rendering.
    • DiffReport: change report between two rule sets.
    • FixHint: remediation suggestion generated from an audit finding.
    • AddressRange: closed IPv4 interval used by coverage analysis.
    • AggregationReport: CIDR deduplication and sibling merge result.
    • ImportReport: structured native, Nginx, or CSV import result.
    • GatePolicy and GateResult: configurable CI release decision.

    Common functions:

    • IPv4::parse
    • CidrBlock::parse
    • Rule::parse
    • parse_rules
    • RuleSet::audit
    • RuleSet::audit_with_policy
    • RuleSet::decide
    • RuleSet::explain_ip
    • RuleSet::diff_from
    • RuleSet::coverage_ranges
    • RuleSet::coverage_report
    • aggregate_cidr_strings
    • import_nginx_access
    • import_csv_rules
    • AuditReport::evaluate_gate
    • AuditReport::text_report
    • AuditReport::json_report
    • AuditReport::hint_report

    #Project Boundary

    MoonCIDR Audit currently focuses on IPv4 and ordered CIDR rules. It does not implement IPv6, kernel integration, packet capture, live network access, or cloud-provider credentials. Its importers are intentionally offline and limited to reviewable text formats. Provider-specific adapters can be added later without changing the core audit model.

    #Hackathon Value

    MoonBit already has examples and packages around networking, URLs, sockets, and general parsing. MoonCIDR Audit targets a different gap: auditing network rule sets before they are deployed. This is useful for configuration review, CI checks, teaching network rule behavior, and building safer MoonBit developer tools.

    #Submission Materials

    • One-page application: docs/submission-application-one-page.md
    • Full application notes: docs/submission-application.md
    • PDF application copy: docs/submission-application.pdf
    • Novelty review: docs/novelty-review.md
    • Submission checklist: docs/submission-checklist.md

    #License

    Apache-2.0.

    AddressRange

    pub struct AddressRange {
    first : IPv4
    last : IPv4
    source_count : Int
    } derive(Eq,
    Debug
    )

    A closed IPv4 address interval.

    source_count records how many original intervals contributed to this range after union operations. It is useful when explaining why a range was produced, but does not change equality or containment semantics.

    AddressRange::address_count_label

    fn AddressRange::address_count_label(self : AddressRange) -> String

    AddressRange::contains_ip

    fn AddressRange::contains_ip(self : AddressRange, ip : IPv4) -> Bool

    AddressRange::contains_range

    fn AddressRange::contains_range(self : AddressRange, other : AddressRange) -> Bool

    AddressRange::first

    fn AddressRange::first(self : AddressRange) -> IPv4

    AddressRange::from_block

    fn AddressRange::from_block(block : CidrBlock) -> AddressRange

    AddressRange::last

    fn AddressRange::last(self : AddressRange) -> IPv4

    AddressRange::merge

    fn AddressRange::merge(self : AddressRange, other : AddressRange) -> Result[AddressRange, String]

    AddressRange::new

    fn AddressRange::new(first : IPv4, last : IPv4, source_count? : Int) -> Result[AddressRange, String]

    AddressRange::overlaps

    fn AddressRange::overlaps(self : AddressRange, other : AddressRange) -> Bool

    AddressRange::source_count

    fn AddressRange::source_count(self : AddressRange) -> Int

    AddressRange::summary

    fn AddressRange::summary(self : AddressRange) -> String

    AddressRange::to_string

    fn AddressRange::to_string(self : AddressRange) -> String

    AddressRange::touches

    fn AddressRange::touches(self : AddressRange, other : AddressRange) -> Bool

    AggregationReport

    pub struct AggregationReport {
    input_count : Int
    valid_count : Int
    duplicate_count : Int
    contained_count : Int
    merged_pair_count : Int
    blocks : Array[CidrBlock]
    errors : Array[String]
    } derive(
    Debug
    )

    Result of normalizing, deduplicating, and aggregating CIDR blocks.

    AggregationReport::blocks

    AggregationReport::changed

    fn AggregationReport::changed(self : AggregationReport) -> Bool

    AggregationReport::contained_count

    fn AggregationReport::contained_count(self : AggregationReport) -> Int

    AggregationReport::duplicate_count

    fn AggregationReport::duplicate_count(self : AggregationReport) -> Int

    AggregationReport::errors

    fn AggregationReport::errors(self : AggregationReport) -> Array[String]

    AggregationReport::input_count

    fn AggregationReport::input_count(self : AggregationReport) -> Int

    AggregationReport::merged_pair_count

    fn AggregationReport::merged_pair_count(self : AggregationReport) -> Int

    AggregationReport::output_count

    fn AggregationReport::output_count(self : AggregationReport) -> Int

    AggregationReport::reduction_count

    fn AggregationReport::reduction_count(self : AggregationReport) -> Int

    AggregationReport::summary

    fn AggregationReport::summary(self : AggregationReport) -> String

    AggregationReport::text_report

    fn AggregationReport::text_report(self : AggregationReport) -> String

    AggregationReport::valid_count

    fn AggregationReport::valid_count(self : AggregationReport) -> Int

    AuditPolicy

    pub struct AuditPolicy {
    wide_allow_prefix : Int
    flag_private : Bool
    flag_special_ranges : Bool
    flag_non_canonical : Bool
    flag_redundant_overlap : Bool
    } derive(Eq,
    Debug
    )

    Controls how noisy or strict CIDR audits should be.

    AuditPolicy::flag_non_canonical

    fn AuditPolicy::flag_non_canonical(self : AuditPolicy) -> Bool

    AuditPolicy::flag_private

    fn AuditPolicy::flag_private(self : AuditPolicy) -> Bool

    AuditPolicy::flag_redundant_overlap

    fn AuditPolicy::flag_redundant_overlap(self : AuditPolicy) -> Bool

    AuditPolicy::flag_special_ranges

    fn AuditPolicy::flag_special_ranges(self : AuditPolicy) -> Bool

    AuditPolicy::gateway

    fn AuditPolicy::gateway() -> AuditPolicy

    AuditPolicy::quiet

    fn AuditPolicy::quiet() -> AuditPolicy

    AuditPolicy::strict

    fn AuditPolicy::strict() -> AuditPolicy

    AuditPolicy::wide_allow_prefix

    fn AuditPolicy::wide_allow_prefix(self : AuditPolicy) -> Int

    AuditReport

    pub struct AuditReport {
    rules : Array[Rule]
    findings : Array[Finding]
    parse_errors : Array[String]
    } derive(
    Debug
    )

    AuditReport::count_hint_kind

    fn AuditReport::count_hint_kind(self : AuditReport, kind : HintKind) -> Int

    AuditReport::count_kind

    fn AuditReport::count_kind(self : AuditReport, kind : FindingKind) -> Int

    AuditReport::count_severity

    fn AuditReport::count_severity(self : AuditReport, severity : Severity) -> Int

    AuditReport::critical_count

    fn AuditReport::critical_count(self : AuditReport) -> Int

    AuditReport::evaluate_gate

    fn AuditReport::evaluate_gate(self : AuditReport, policy : GatePolicy) -> GateResult

    AuditReport::finding_count

    fn AuditReport::finding_count(self : AuditReport) -> Int

    AuditReport::findings

    fn AuditReport::findings(self : AuditReport) -> Array[Finding]

    AuditReport::fix_hints

    fn AuditReport::fix_hints(self : AuditReport) -> Array[FixHint]

    AuditReport::hint_report

    fn AuditReport::hint_report(self : AuditReport) -> String

    AuditReport::info_count

    fn AuditReport::info_count(self : AuditReport) -> Int

    AuditReport::json_report

    fn AuditReport::json_report(self : AuditReport) -> String

    Builds a stable JSON-like report without external dependencies.

    AuditReport::parse_errors

    fn AuditReport::parse_errors(self : AuditReport) -> Array[String]

    AuditReport::recommended_action

    fn AuditReport::recommended_action(self : AuditReport) -> String

    AuditReport::risk_level

    fn AuditReport::risk_level(self : AuditReport) -> String

    AuditReport::risk_score

    fn AuditReport::risk_score(self : AuditReport) -> Int

    AuditReport::rules

    fn AuditReport::rules(self : AuditReport) -> Array[Rule]

    AuditReport::summary_table

    fn AuditReport::summary_table(self : AuditReport) -> String

    AuditReport::text_report

    fn AuditReport::text_report(self : AuditReport) -> String

    Builds a compact human-readable audit report.

    AuditReport::warning_count

    fn AuditReport::warning_count(self : AuditReport) -> Int

    CidrBlock

    pub struct CidrBlock {
    network : IPv4
    prefix : Int
    } derive(Eq,
    Debug
    )

    A normalized IPv4 CIDR block.

    CidrBlock::broadcast

    fn CidrBlock::broadcast(self : CidrBlock) -> IPv4

    CidrBlock::contains_block

    fn CidrBlock::contains_block(self : CidrBlock, other : CidrBlock) -> Bool

    CidrBlock::contains_ip

    fn CidrBlock::contains_ip(self : CidrBlock, ip : IPv4) -> Bool

    CidrBlock::equal_range

    fn CidrBlock::equal_range(self : CidrBlock, other : CidrBlock) -> Bool

    CidrBlock::has_host_bits

    fn CidrBlock::has_host_bits(input : String) -> Bool

    CidrBlock::network

    fn CidrBlock::network(self : CidrBlock) -> IPv4

    CidrBlock::new

    fn CidrBlock::new(address : IPv4, prefix : Int) -> Result[CidrBlock, String]

    CidrBlock::new_unchecked

    fn CidrBlock::new_unchecked(network : IPv4, prefix : Int) -> CidrBlock

    CidrBlock::overlaps

    fn CidrBlock::overlaps(self : CidrBlock, other : CidrBlock) -> Bool

    CidrBlock::parse

    fn CidrBlock::parse(input : String) -> Result[CidrBlock, String]

    CidrBlock::parse_raw

    fn CidrBlock::parse_raw(input : String) -> Result[(IPv4, Int), String]

    CidrBlock::prefix

    fn CidrBlock::prefix(self : CidrBlock) -> Int

    CidrBlock::size_label

    fn CidrBlock::size_label(self : CidrBlock) -> String

    CidrBlock::to_string

    fn CidrBlock::to_string(self : CidrBlock) -> String

    CoverageStats

    pub struct CoverageStats {
    total_rules : Int
    allow_rules : Int
    deny_rules : Int
    private_rules : Int
    public_rules : Int
    special_rules : Int
    widest_prefix : Int
    narrowest_prefix : Int
    } derive(Eq,
    Debug
    )

    Aggregate facts about a rule set.

    CoverageStats::allow_rules

    fn CoverageStats::allow_rules(self : CoverageStats) -> Int

    CoverageStats::deny_rules

    fn CoverageStats::deny_rules(self : CoverageStats) -> Int

    CoverageStats::narrowest_prefix

    fn CoverageStats::narrowest_prefix(self : CoverageStats) -> Int

    CoverageStats::private_rules

    fn CoverageStats::private_rules(self : CoverageStats) -> Int

    CoverageStats::public_rules

    fn CoverageStats::public_rules(self : CoverageStats) -> Int

    CoverageStats::special_rules

    fn CoverageStats::special_rules(self : CoverageStats) -> Int

    CoverageStats::summary

    fn CoverageStats::summary(self : CoverageStats) -> String

    CoverageStats::total_rules

    fn CoverageStats::total_rules(self : CoverageStats) -> Int

    CoverageStats::widest_prefix

    fn CoverageStats::widest_prefix(self : CoverageStats) -> Int

    Decision

    pub struct Decision {
    matched : Bool
    action : RuleAction
    rule_id : String
    block : String
    } derive(Eq,
    Debug
    )

    Decision::action

    fn Decision::action(self : Decision) -> RuleAction

    Decision::block

    fn Decision::block(self : Decision) -> String

    Decision::matched

    fn Decision::matched(self : Decision) -> Bool

    Decision::rule_id

    fn Decision::rule_id(self : Decision) -> String

    Decision::summary

    fn Decision::summary(self : Decision) -> String

    DiffReport

    pub struct DiffReport {
    changes : Array[RuleChange]
    } derive(
    Debug
    )

    DiffReport::change_count

    fn DiffReport::change_count(self : DiffReport) -> Int

    DiffReport::changes

    fn DiffReport::changes(self : DiffReport) -> Array[RuleChange]

    DiffReport::count_kind

    fn DiffReport::count_kind(self : DiffReport, kind : RuleChangeKind) -> Int

    DiffReport::is_empty

    fn DiffReport::is_empty(self : DiffReport) -> Bool

    DiffReport::risk_level

    fn DiffReport::risk_level(self : DiffReport) -> String

    DiffReport::risky_count

    fn DiffReport::risky_count(self : DiffReport) -> Int

    DiffReport::text_report

    fn DiffReport::text_report(self : DiffReport) -> String

    Finding

    pub struct Finding {
    kind : FindingKind
    severity : Severity
    rule_id : String
    related_rule_id : String
    message : String
    } derive(Eq,
    Debug
    )

    Finding::kind

    fn Finding::kind(self : Finding) -> FindingKind

    Finding::message

    fn Finding::message(self : Finding) -> String

    Finding::new

    fn Finding::new(kind : FindingKind, severity : Severity, rule_id : String, message : String, related_rule_id? : String) -> Finding

    Finding::related_rule_id

    fn Finding::related_rule_id(self : Finding) -> String

    Finding::rule_id

    fn Finding::rule_id(self : Finding) -> String

    Finding::severity

    fn Finding::severity(self : Finding) -> Severity

    FindingKind

    pub(all) enum FindingKind {
    DuplicateRule
    ShadowedRule
    ConflictingOverlap
    RedundantOverlap
    TooWideAllow
    GlobalDeny
    PrivateRange
    LoopbackRange
    LinkLocalRange
    MulticastRange
    NonCanonicalCidr
    ParseError
    } derive(Eq,
    Debug
    )

    Classifies why a rule deserves attention.

    FindingKind::label

    fn FindingKind::label(self : FindingKind) -> String

    FixHint

    pub struct FixHint {
    kind : HintKind
    severity : Severity
    rule_id : String
    text : String
    } derive(Eq,
    Debug
    )

    FixHint::kind

    fn FixHint::kind(self : FixHint) -> HintKind

    FixHint::new

    fn FixHint::new(kind : HintKind, severity : Severity, rule_id : String, text : String) -> FixHint

    FixHint::rule_id

    fn FixHint::rule_id(self : FixHint) -> String

    FixHint::severity

    fn FixHint::severity(self : FixHint) -> Severity

    FixHint::summary

    fn FixHint::summary(self : FixHint) -> String

    FixHint::text

    fn FixHint::text(self : FixHint) -> String

    GatePolicy

    pub struct GatePolicy {
    name : String
    max_critical : Int
    max_warning : Int
    max_risk_score : Int
    allow_parse_errors : Bool
    } derive(Eq,
    Debug
    )

    Thresholds used to decide whether a rule set may pass a CI or release gate.

    GatePolicy::allow_parse_errors

    fn GatePolicy::allow_parse_errors(self : GatePolicy) -> Bool

    GatePolicy::development

    fn GatePolicy::development() -> GatePolicy

    Development policy: blocks only very risky reports and parse failures.

    GatePolicy::max_critical

    fn GatePolicy::max_critical(self : GatePolicy) -> Int

    GatePolicy::max_risk_score

    fn GatePolicy::max_risk_score(self : GatePolicy) -> Int

    GatePolicy::max_warning

    fn GatePolicy::max_warning(self : GatePolicy) -> Int

    GatePolicy::name

    fn GatePolicy::name(self : GatePolicy) -> String

    GatePolicy::new

    fn GatePolicy::new(name : String, max_critical : Int, max_warning : Int, max_risk_score : Int, allow_parse_errors? : Bool) -> Result[GatePolicy, String]

    GatePolicy::release

    fn GatePolicy::release() -> GatePolicy

    Strict release policy: no critical findings, warnings, or parse errors.

    GatePolicy::review

    fn GatePolicy::review() -> GatePolicy

    Review policy: allows a small warning budget but no critical findings.

    GatePolicy::summary

    fn GatePolicy::summary(self : GatePolicy) -> String

    GateReason

    pub struct GateReason {
    code : String
    actual : Int
    limit : Int
    message : String
    } derive(Eq,
    Debug
    )

    GateReason::actual

    fn GateReason::actual(self : GateReason) -> Int

    GateReason::code

    fn GateReason::code(self : GateReason) -> String

    GateReason::limit

    fn GateReason::limit(self : GateReason) -> Int

    GateReason::message

    fn GateReason::message(self : GateReason) -> String

    GateReason::new

    fn GateReason::new(code : String, actual : Int, limit : Int, message : String) -> GateReason

    GateReason::summary

    fn GateReason::summary(self : GateReason) -> String

    GateResult

    pub struct GateResult {
    policy : GatePolicy
    passed : Bool
    risk_score : Int
    reasons : Array[GateReason]
    } derive(
    Debug
    )

    GateResult::decision

    fn GateResult::decision(self : GateResult) -> String

    GateResult::has_reason

    fn GateResult::has_reason(self : GateResult, code : String) -> Bool

    GateResult::passed

    fn GateResult::passed(self : GateResult) -> Bool

    GateResult::policy

    fn GateResult::policy(self : GateResult) -> GatePolicy

    GateResult::reason_count

    fn GateResult::reason_count(self : GateResult) -> Int

    GateResult::reasons

    fn GateResult::reasons(self : GateResult) -> Array[GateReason]

    GateResult::risk_score

    fn GateResult::risk_score(self : GateResult) -> Int

    GateResult::text_report

    fn GateResult::text_report(self : GateResult) -> String

    HintKind

    pub(all) enum HintKind {
    MoveSpecificRule
    TightenCidr
    ConfirmDefaultPolicy
    CanonicalizeInput
    RemoveDuplicate
    ReviewSpecialScope
    FixSyntax
    ReviewOverlap
    } derive(Eq,
    Debug
    )

    Category of remediation hint produced from audit findings.

    HintKind::label

    fn HintKind::label(self : HintKind) -> String

    IPv4

    pub struct IPv4 {
    value : UInt
    } derive(Eq,
    Debug
    )

    A parsed IPv4 address stored as an unsigned 32-bit integer.

    IPv4::is_limited_broadcast

    fn IPv4::is_limited_broadcast(self : IPv4) -> Bool

    fn IPv4::is_link_local(self : IPv4) -> Bool

    IPv4::is_loopback

    fn IPv4::is_loopback(self : IPv4) -> Bool

    IPv4::is_multicast

    fn IPv4::is_multicast(self : IPv4) -> Bool

    IPv4::is_private

    fn IPv4::is_private(self : IPv4) -> Bool

    IPv4::is_public

    fn IPv4::is_public(self : IPv4) -> Bool

    Returns true when the address is not one of the private or special scopes currently recognized by this package.

    IPv4::is_unspecified

    fn IPv4::is_unspecified(self : IPv4) -> Bool

    IPv4::new

    fn IPv4::new(value : UInt) -> IPv4

    IPv4::parse

    fn IPv4::parse(input : String) -> Result[IPv4, String]

    IPv4::scope_label

    fn IPv4::scope_label(self : IPv4) -> String

    IPv4::to_dotted

    fn IPv4::to_dotted(self : IPv4) -> String

    IPv4::value

    fn IPv4::value(self : IPv4) -> UInt

    ImportFormat

    pub(all) enum ImportFormat {
    PlainRules
    NginxAccess
    CsvRules
    } derive(Eq,
    Debug
    )

    Input syntax understood by the configuration import layer.

    ImportFormat::label

    fn ImportFormat::label(self : ImportFormat) -> String

    ImportIssue

    pub struct ImportIssue {
    line : Int
    level : ImportIssueLevel
    code : String
    message : String
    input : String
    } derive(Eq,
    Debug
    )

    ImportIssue::code

    fn ImportIssue::code(self : ImportIssue) -> String

    ImportIssue::input

    fn ImportIssue::input(self : ImportIssue) -> String

    ImportIssue::level

    ImportIssue::line

    fn ImportIssue::line(self : ImportIssue) -> Int

    ImportIssue::message

    fn ImportIssue::message(self : ImportIssue) -> String

    ImportIssue::new

    fn ImportIssue::new(line : Int, level : ImportIssueLevel, code : String, message : String, input : String) -> ImportIssue

    ImportIssue::summary

    fn ImportIssue::summary(self : ImportIssue) -> String

    ImportIssueLevel

    pub(all) enum ImportIssueLevel {
    ImportWarning
    ImportError
    } derive(Eq,
    Debug
    )

    ImportIssueLevel::label

    fn ImportIssueLevel::label(self : ImportIssueLevel) -> String

    ImportReport

    pub struct ImportReport {
    format : ImportFormat
    source_count : Int
    rules : Array[Rule]
    issues : Array[ImportIssue]
    } derive(
    Debug
    )

    ImportReport::accepted_count

    fn ImportReport::accepted_count(self : ImportReport) -> Int

    ImportReport::can_audit

    fn ImportReport::can_audit(self : ImportReport) -> Bool

    ImportReport::error_count

    fn ImportReport::error_count(self : ImportReport) -> Int

    ImportReport::format

    fn ImportReport::format(self : ImportReport) -> ImportFormat

    ImportReport::is_clean

    fn ImportReport::is_clean(self : ImportReport) -> Bool

    ImportReport::issues

    ImportReport::rules

    fn ImportReport::rules(self : ImportReport) -> Array[Rule]

    ImportReport::source_count

    fn ImportReport::source_count(self : ImportReport) -> Int

    ImportReport::summary

    fn ImportReport::summary(self : ImportReport) -> String

    ImportReport::text_report

    fn ImportReport::text_report(self : ImportReport) -> String

    ImportReport::to_ruleset

    fn ImportReport::to_ruleset(self : ImportReport) -> RuleSet

    ImportReport::warning_count

    fn ImportReport::warning_count(self : ImportReport) -> Int

    Rule

    pub struct Rule {
    id : String
    action : RuleAction
    block : CidrBlock
    source_block : String
    note : String
    } derive(Eq,
    Debug
    )

    A single ordered firewall, proxy, or gateway rule.

    Rule::action

    fn Rule::action(self : Rule) -> RuleAction

    Rule::block

    fn Rule::block(self : Rule) -> CidrBlock

    Rule::id

    fn Rule::id(self : Rule) -> String

    Rule::is_canonical

    fn Rule::is_canonical(self : Rule) -> Bool

    Rule::matches

    fn Rule::matches(self : Rule, ip : IPv4) -> Bool

    Rule::new

    fn Rule::new(id : String, action : RuleAction, block : CidrBlock, source_block? : String, note? : String) -> Rule

    Rule::note

    fn Rule::note(self : Rule) -> String

    Rule::parse

    fn Rule::parse(id : String, line : String) -> Result[Rule, String]

    Rule::same_decision

    fn Rule::same_decision(self : Rule, other : Rule) -> Bool

    Rule::source_block

    fn Rule::source_block(self : Rule) -> String

    Rule::summary

    fn Rule::summary(self : Rule) -> String

    RuleAction

    pub(all) enum RuleAction {
    Allow
    Deny
    } derive(Eq,
    Debug
    )

    Action taken when a CIDR rule matches.

    RuleAction::label

    fn RuleAction::label(self : RuleAction) -> String

    RuleAction::parse

    fn RuleAction::parse(input : String) -> Result[RuleAction, String]

    RuleChange

    pub struct RuleChange {
    kind : RuleChangeKind
    before_id : String
    after_id : String
    block : String
    message : String
    } derive(Eq,
    Debug
    )

    A change item matched by CIDR range.

    RuleChange::after_id

    fn RuleChange::after_id(self : RuleChange) -> String

    RuleChange::before_id

    fn RuleChange::before_id(self : RuleChange) -> String

    RuleChange::block

    fn RuleChange::block(self : RuleChange) -> String

    RuleChange::kind

    RuleChange::message

    fn RuleChange::message(self : RuleChange) -> String

    RuleChange::new

    fn RuleChange::new(kind : RuleChangeKind, before_id : String, after_id : String, block : String, message : String) -> RuleChange

    RuleChange::summary

    fn RuleChange::summary(self : RuleChange) -> String

    RuleChangeKind

    pub(all) enum RuleChangeKind {
    AddedRule
    RemovedRule
    ActionChanged
    NoteChanged
    UnchangedRule
    } derive(Eq,
    Debug
    )

    Type of change between two rule sets.

    RuleChangeKind::is_risky

    fn RuleChangeKind::is_risky(self : RuleChangeKind) -> Bool

    RuleChangeKind::label

    fn RuleChangeKind::label(self : RuleChangeKind) -> String

    RuleSet

    pub struct RuleSet {
    rules : Array[Rule]
    parse_errors : Array[String]
    } derive(
    Debug
    )

    RuleSet::audit

    fn RuleSet::audit(self : RuleSet) -> AuditReport

    RuleSet::audit_with_policy

    fn RuleSet::audit_with_policy(self : RuleSet, policy : AuditPolicy) -> AuditReport

    RuleSet::coverage_ranges

    fn RuleSet::coverage_ranges(self : RuleSet, action : RuleAction) -> Array[AddressRange]

    Returns the union of all rule blocks with the requested action.

    This is a structural view. Ordered first-match behavior is intentionally handled separately by RuleSet::decide.

    RuleSet::coverage_report

    fn RuleSet::coverage_report(self : RuleSet, action : RuleAction, target : CidrBlock) -> String

    RuleSet::coverage_stats

    fn RuleSet::coverage_stats(self : RuleSet) -> CoverageStats

    RuleSet::decide

    fn RuleSet::decide(self : RuleSet, ip : IPv4) -> Decision

    RuleSet::diff_from

    fn RuleSet::diff_from(self : RuleSet, previous : RuleSet) -> DiffReport

    RuleSet::evaluate_gate

    fn RuleSet::evaluate_gate(self : RuleSet, audit_policy : AuditPolicy, gate_policy : GatePolicy) -> GateResult

    RuleSet::explain_ip

    fn RuleSet::explain_ip(self : RuleSet, ip : IPv4) -> String

    RuleSet::explain_many

    fn RuleSet::explain_many(self : RuleSet, probes : Array[String]) -> String

    RuleSet::first_rule_for_block

    fn RuleSet::first_rule_for_block(self : RuleSet, block : CidrBlock) -> String

    RuleSet::from_lines

    fn RuleSet::from_lines(lines : Array[String]) -> RuleSet

    RuleSet::inventory_report

    fn RuleSet::inventory_report(self : RuleSet) -> String

    RuleSet::matching_rules

    fn RuleSet::matching_rules(self : RuleSet, ip : IPv4) -> Array[Rule]

    RuleSet::new

    fn RuleSet::new(rules : Array[Rule]) -> RuleSet

    RuleSet::parse_errors

    fn RuleSet::parse_errors(self : RuleSet) -> Array[String]

    RuleSet::rules

    fn RuleSet::rules(self : RuleSet) -> Array[Rule]

    Severity

    pub(all) enum Severity {
    Info
    Warning
    Critical
    } derive(Eq,
    Debug
    )

    Severity assigned to an audit finding.

    Severity::label

    fn Severity::label(self : Severity) -> String

    Severity::score

    fn Severity::score(self : Severity) -> Int

    aggregate_blocks

    fn aggregate_blocks(blocks : Array[CidrBlock]) -> AggregationReport

    Aggregates already parsed CIDR blocks.

    aggregate_cidr_strings

    fn aggregate_cidr_strings(inputs : Array[String]) -> AggregationReport

    Parses and aggregates a list of CIDR strings.

    Invalid entries are preserved in errors rather than aborting the whole operation, making the API suitable for configuration linting.

    audit_rules

    fn audit_rules(rules : Array[Rule]) -> AuditReport

    audit_rules_with_policy

    fn audit_rules_with_policy(rules : Array[Rule], policy : AuditPolicy) -> AuditReport

    clip_ranges_to_block

    fn clip_ranges_to_block(target : CidrBlock, coverage : Array[AddressRange]) -> Array[AddressRange]

    Clips address ranges to a target CIDR and returns a merged union.

    diff_rule_sets

    fn diff_rule_sets(current : RuleSet, previous : RuleSet) -> DiffReport

    import_csv_rules

    fn import_csv_rules(lines : Array[String]) -> ImportReport

    Imports rows in action,cidr,note form.

    A header row is optional. Quoted fields, embedded commas, and doubled quote escapes are supported. Extra columns are folded into the note and reported as a warning so information is not silently discarded.

    import_nginx_access

    fn import_nginx_access(lines : Array[String]) -> ImportReport

    Imports Nginx access directives such as allow 10.0.0.0/8;.

    deny all; and allow all; are converted to 0.0.0.0/0. Other Nginx directives are rejected so accidental input from an unrelated section is visible to the caller.

    import_plain_rules

    fn import_plain_rules(lines : Array[String]) -> ImportReport

    Imports the native compact syntax: allow 10.0.0.0/8 note.

    merge_address_ranges

    fn merge_address_ranges(input : Array[AddressRange]) -> Array[AddressRange]

    Sorts and merges overlapping or adjacent address ranges.

    parse_rules

    fn parse_rules(lines : Array[String]) -> RuleSet

    ranges_from_blocks

    fn ranges_from_blocks(blocks : Array[CidrBlock]) -> Array[AddressRange]

    Converts CIDR blocks into a sorted, non-overlapping union of address ranges.

    uncovered_ranges

    fn uncovered_ranges(target : CidrBlock, coverage : Array[AddressRange]) -> Array[AddressRange]

    Finds holes inside target that are not covered by any supplied range.