Exgit.Credentials (exgit v0.1.0)

Copy Markdown View Source

Helpers for constructing transport auth values, plus a small host-scoped credential mechanism.

The flat constructors (basic/2, bearer/1) return raw auth tuples suitable for Exgit.Transport.HTTP.new/2 — callers who know exactly which URL they're talking to typically use these directly.

host_bound/2 and for_host/2 add a safety rail: a credential is only surrendered when the target URL's host matches the bound pattern. This guards against accidentally leaking a GitHub token to an attacker-controlled redirect, a CI misconfiguration, or a user- supplied URL that points somewhere unexpected.

Host matching

for_host/2 normalizes the URL's host before comparing it against the pattern:

  • case-folded via String.downcase/1 (ASCII only — we refuse to recognize tokens for a Unicode TLD; IDN hosts must be supplied in punycode)
  • trailing . (DNS fully-qualified form) stripped
  • Unicode/IDN hosts are NOT normalized — callers who need IDN matching must provide the punycode host explicitly

Patterns:

  • Exact hostname: "github.com" matches only github.com (case-insensitive).
  • Wildcard: "*.githubusercontent.com" matches githubusercontent.com AND any x.githubusercontent.com. A single-component wildcard label is required — the pattern must start with *..

No regex, no substring matching, no glob.

Summary

Functions

Rewrap an existing host-bound credential to bind to pattern. Useful in a pipeline

Return the auth value iff the credential's host binding matches the given URL. Returns :none otherwise.

Wrap an auth value with a host pattern. The pattern is either a bare hostname ("github.com") or a wildcard ("*.githubusercontent.com"). Use for_host/2 to extract the auth when (and only when) the URL matches.

Wrap an auth value without a host binding. Emits the auth for any URL — caller has explicitly opted out of scoping.

Types

auth()

host_cred()

@type host_cred() :: %Exgit.Credentials{auth: auth(), host_pattern: String.t() | :any}

t()

@type t() :: host_cred()

Functions

basic(user, password)

@spec basic(String.t(), String.t()) :: auth()

bearer(token)

@spec bearer(String.t()) :: auth()

bind_to(auth, pattern)

@spec bind_to(auth() | host_cred(), String.t()) :: host_cred()

Rewrap an existing host-bound credential to bind to pattern. Useful in a pipeline:

Credentials.bearer(token) |> Credentials.bind_to("github.com")

If the input is a bare auth tuple, bind_to/2 wraps it in a fresh %Credentials{}. If it's already a %Credentials{} struct, the existing auth is reused with the new pattern.

for_host(credentials, url)

@spec for_host(host_cred(), String.t()) :: {:ok, auth()} | :none

Return the auth value iff the credential's host binding matches the given URL. Returns :none otherwise.

host_bound(pattern, auth)

@spec host_bound(String.t(), auth()) :: host_cred()

Wrap an auth value with a host pattern. The pattern is either a bare hostname ("github.com") or a wildcard ("*.githubusercontent.com"). Use for_host/2 to extract the auth when (and only when) the URL matches.

unbound(auth)

@spec unbound(auth()) :: host_cred()

Wrap an auth value without a host binding. Emits the auth for any URL — caller has explicitly opted out of scoping.