Skip to main content

Crate devboy_secret_patterns

Crate devboy_secret_patterns 

Source
Expand description

Pattern catalogue for devboy-tools secrets.

A secret pattern is everything we know about a kind of secret — “what does a GitHub Personal Access Token look like, where does the user obtain a fresh one, how often should it be rotated, how can we tell whether a candidate value is still alive”. One pattern, many consumers:

  • The secret store (ADR-020 / ADR-023) reads format_regex for validation, metadata().retrieval_url_template for the [Open URL] button in the rotation flow, rotation() for the doctor cadence reminder, liveness() for the secrets validate probe.
  • The OTLP sanitizer (#240) and otel scan auditor (#242) read format_regex and severity only — they don’t care about retrieval or rotation, just “is this string a leaked secret?”.

The trait is layered so the two consumers can ignore the parts they don’t need without forcing the catalogue to fill in fields it doesn’t have. Mandatory: id, display_name, format_regex, severity. Optional: metadata, rotation, liveness.

See ADR-023 §3.6 for the design rationale.

§Example

Implementing a minimal pattern (mandatory fields only) for a made-up provider:

use devboy_secret_patterns::{SecretPattern, Severity};
use regex::Regex;
use std::sync::OnceLock;

struct ExampleProviderToken;

impl SecretPattern for ExampleProviderToken {
    fn id(&self) -> &str { "example-provider-token" }
    fn display_name(&self) -> &str { "Example Provider API Token" }
    fn severity(&self) -> Severity { Severity::High }

    fn format_regex(&self) -> &Regex {
        static R: OnceLock<Regex> = OnceLock::new();
        R.get_or_init(|| Regex::new(r"^example_[A-Za-z0-9]{32}$").unwrap())
    }
}

let p = ExampleProviderToken;
assert_eq!(p.id(), "example-provider-token");
assert_eq!(p.severity(), Severity::High);
assert!(p.format_regex().is_match("example_abcdefghijklmnopqrstuvwxyz012345"));
assert!(!p.format_regex().is_match("nope"));
// Optional layers default to None.
assert!(p.metadata().is_none());
assert!(p.rotation().is_none());
assert!(p.liveness().is_none());

Re-exports§

pub use builtin::BUILTINS;
pub use builtin::Builtin;
pub use builtin::builtins;
pub use builtin::find;
pub use user::Catalogue;
pub use user::LoadError;
pub use user::LoadWarning;
pub use user::LoadWarningKind;
pub use user::UserPattern;
pub use user::UserPatternFile;

Modules§

builtin
Built-in pattern catalogue per ADR-023 §3.6.
user
User-supplied pattern extension per ADR-023 §3.6.

Structs§

LivenessSpec
Optional liveness specification for a pattern.
PatternMetadata
Optional descriptive metadata for a pattern. Consumed by the secret store’s pattern_id inheritance (epic phase P2.4) and by the UI.
RotationSpec
Optional rotation hint for a pattern.

Enums§

HttpMethod
HTTP method for liveness probes.
LivenessAuth
How to attach the candidate secret to the liveness HTTP request.
LivenessKind
Liveness probe shape — currently only HTTP, but the enum gives us room to add subprocess- or socket-based probes later without breaking the trait.
RotationMethodSpec
How a secret of this kind is rotated.
Severity
How dangerous a leak of this kind of secret is.

Traits§

SecretPattern
One kind of secret in the catalogue.