moon_scrub

    Offline sensitive-data detection and redaction for MoonBit applications.

    security
    redaction
    secrets
    pii
    logs
    Download zip
    Author
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    last month
    Downloads
    25

    No dependencies

    #Moon Scrub

    Offline sensitive-data detection and redaction for MoonBit applications. Findings contain category, confidence, and UTF-16 offsets, but never retain the matched value.

    #Public API

    • scan(text, policy~) -> Array[Finding]
    • redact(text, style~, policy~) -> RedactionResult
    • verify_clean(text, policy~) -> Bool
    • redact_batch(lines, style~, policy~) -> BatchResult
    • scan_with_rules(text, rules, policy~) -> Array[Finding]
    • redact_with_rules(text, rules, style~, policy~) -> RedactionResult
    • redact_fields(fields, style~, policy~) -> StructuredResult
    • ScanPolicy::secrets_only() and ScanPolicy::standard()

    Detectors cover structured access tokens, bearer credentials, JWTs, sensitive assignments, email addresses, IPv4 addresses, and Luhn-valid payment-card candidates. This is a deterministic helper, not a complete DLP or compliance system. See the repository README and security model for limitations.

    BatchResult

    pub(all) struct BatchResult {
    lines : Array[String]
    summary : BatchSummary
    } derive(Eq,
    Debug
    )

    BatchSummary

    pub(all) struct BatchSummary {
    lines : Int
    changed_lines : Int
    findings : Int
    access_tokens : Int
    bearer_tokens : Int
    jwts : Int
    credentials : Int
    emails : Int
    ipv4s : Int
    payment_cards : Int
    private_keys : Int
    url_credentials : Int
    custom_secrets : Int
    } derive(Eq,
    Debug
    )

    Confidence

    pub(all) enum Confidence {
    High
    Medium
    } derive(Eq,
    Debug
    )

    CustomRule

    pub(all) struct CustomRule {
    label : String
    value : String
    } derive(Eq,
    Debug
    )

    A caller-supplied exact value that should never leave the process. Rules shorter than four UTF-16 code units are ignored to limit accidental broad matches. The label is metadata only and never appears in output markers.

    Finding

    pub(all) struct Finding {
    kind : SensitiveKind
    start : Int
    end : Int
    confidence : Confidence
    } derive(Eq,
    Debug
    )

    Half-open UTF-16 offsets. A finding never stores or returns the matched value, making reports safer to log than the original input.

    RedactionResult

    pub(all) struct RedactionResult {
    text : String
    findings : Array[Finding]
    changed : Bool
    } derive(Eq,
    Debug
    )

    RedactionStyle

    pub(all) enum RedactionStyle {
    Marker
    Typed
    PreserveLast4
    } derive(Eq,
    Debug
    )

    ScanPolicy

    pub(all) struct ScanPolicy {
    detect_email : Bool
    detect_ipv4 : Bool
    detect_payment_card : Bool
    } derive(Eq,
    Debug
    )

    A policy controls which detector families run. Known credentials are always enabled because suppressing them creates surprising leak paths.

    ScanPolicy::secrets_only

    fn ScanPolicy::secrets_only() -> ScanPolicy

    ScanPolicy::standard

    fn ScanPolicy::standard() -> ScanPolicy

    SensitiveKind

    pub(all) enum SensitiveKind {
    AccessToken
    BearerToken
    Jwt
    CredentialAssignment
    Email
    Ipv4
    PaymentCard
    PrivateKey
    UrlCredential
    CustomSecret
    } derive(Eq,
    Debug
    )

    Detection categories intentionally stay small and auditable. This library detects structured secrets and common identifiers; it is not an NLP system.

    SensitiveKind::to_string

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

    StructuredField

    pub(all) struct StructuredField {
    path : String
    value : String
    } derive(Eq,
    Debug
    )

    Domain-neutral structured field adapter. path may be a JSON pointer, dotted property path, form field name, or database column name.

    StructuredFieldResult

    pub(all) struct StructuredFieldResult {
    path : String
    value : String
    findings : Array[Finding]
    changed : Bool
    sensitive_path : Bool
    } derive(Eq,
    Debug
    )

    StructuredResult

    pub(all) struct StructuredResult {
    fields : Array[StructuredFieldResult]
    changed_fields : Int
    findings : Int
    } derive(Eq,
    Debug
    )

    redact

    fn redact(text : String, style? : RedactionStyle, policy? : ScanPolicy) -> RedactionResult

    Redact all enabled findings. Already-produced markers contain no detector pattern, so applying the same policy again is idempotent.

    redact_batch

    fn redact_batch(lines : Array[String], style? : RedactionStyle, policy? : ScanPolicy) -> BatchResult

    Redact independent log/API/prompt lines and return aggregate counts. The summary contains categories and counts only, never matched values.

    redact_fields

    fn redact_fields(fields : Array[StructuredField], style? : RedactionStyle, policy? : ScanPolicy) -> StructuredResult

    Redact already-parsed structured fields. Sensitive paths are fail-closed: their complete value is replaced even when its shape matches no detector. Other fields use content scanning. Paths are retained for caller-side joins.

    redact_with_rules

    fn redact_with_rules(text : String, rules : Array[CustomRule], style? : RedactionStyle, policy? : ScanPolicy) -> RedactionResult

    Redact text with built-in and caller-supplied exact-value rules.

    scan

    fn scan(text : String, policy? : ScanPolicy) -> Array[Finding]

    Scan text without retaining sensitive values in the returned findings.

    scan_with_rules

    fn scan_with_rules(text : String, rules : Array[CustomRule], policy? : ScanPolicy) -> Array[Finding]

    Add caller-known exact secrets to the built-in detector set. The returned findings do not carry rule labels or values. Empty and very short values are deliberately ignored.

    verify_clean

    fn verify_clean(text : String, policy? : ScanPolicy) -> Bool

    Return true only when a fresh scan finds no enabled sensitive values.