cowl

Types

Selects which characters to expose in a Peek strategy.

pub type PeekMode {
  First(n: Int)
  Last(n: Int)
  Both(n: Int, m: Int)
}

Constructors

  • First(n: Int)

    First n characters, then the filler.

  • Last(n: Int)

    Filler, then the last n characters.

  • Both(n: Int, m: Int)

    First n characters, filler, then the last m.

An opaque wrapper that keeps a value secret.

The value lives inside a closure, so io.debug, echo, and string.inspect never reveal it. Use cowl.to_string for safe output.

pub opaque type Secret(a)

How to render a secret as text.

pub type Strategy {
  Stars
  Fixed(text: String)
  Label
  Peek(mode: PeekMode, filler: String)
  Custom(f: fn(String) -> String)
}

Constructors

  • Stars

    Always "***".

  • Fixed(text: String)

    A fixed replacement string; the secret value is ignored.

  • Label

    The label in brackets, or "[secret]" if no label is set.

  • Peek(mode: PeekMode, filler: String)

    Show a small window of the secret with filler around it.

  • Custom(f: fn(String) -> String)

    Apply an arbitrary function to the raw value.

Values

pub fn equal(a: Secret(a), b: Secret(a)) -> Bool

Compare two secrets by value — labels are ignored.

pub fn field(secret: Secret(String)) -> #(String, String)

Return #(label, "***") for structured logging. Falls back to "secret" if unlabeled.

pub fn field_with(
  secret: Secret(String),
  strategy: Strategy,
) -> #(String, String)

Like field, with an explicit masking strategy.

pub fn from_result(res: Result(a, e)) -> Result(Secret(a), e)

Wrap the Ok value of a Result as a secret, passing errors through.

pub fn get_label(secret: Secret(a)) -> option.Option(String)

Return the label, if any.

pub fn labeled(value: a, label: String) -> Secret(a)

Wrap value as a secret with a label.

pub fn labeled_from_result(
  res: Result(a, e),
  label: String,
) -> Result(Secret(a), e)

Like from_result, but also attaches a label.

pub fn map(secret: Secret(a), f: fn(a) -> b) -> Secret(b)

Transform the wrapped value while keeping it secret. The label is preserved.

pub fn map_label(
  secret: Secret(a),
  f: fn(String) -> String,
) -> Secret(a)

Transform only the label, leaving the value untouched.

pub fn mask(secret: Secret(String)) -> String

Render a string secret as "***".

pub fn mask_with(
  secret: Secret(String),
  strategy: Strategy,
) -> String

Render a string secret using the given strategy.

pub fn remove_label(secret: Secret(a)) -> Secret(a)

Remove the label from a secret. The value is untouched.

pub fn reveal(secret: Secret(a)) -> a

Unwrap and return the raw value.

pub fn secret(value: a) -> Secret(a)

Wrap value as a secret with no label.

pub fn tap(secret: Secret(a), f: fn(a) -> b) -> Secret(a)

Run f for its side effects and return the original secret unchanged.

⚠️ Never pass a logging function directly — it will print the raw value. Use cowl.to_string for a safe representation instead.

pub fn to_string(secret: Secret(String)) -> String

A safe debug string — always "Secret(***)", never the actual value.

pub fn use_secret(secret: Secret(a), f: fn(a) -> b) -> b

Pass the raw value to f without letting it escape the return type.

pub fn with_label(secret: Secret(a), label: String) -> Secret(a)

Set or replace the label on a secret.

Search Document