config

package
v0.15.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 10, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package config loads runtime settings via koanf in the layered pattern: struct defaults → settings.toml → CHESHMHAYASH__* environment variables.

Env keys use `__` as the path separator (e.g. CHESHMHAYASH__SERVER__PORT). `[]NATS` entries are addressed by their array index — koanf can't merge a numeric-keyed env map into a TOML-loaded slice, so slice paths are overlaid manually after the struct is unmarshalled.

Index

Constants

View Source
const (
	AuthModeOIDC = "oidc"
	AuthModeJWT  = "jwt"
)

Auth mode identifiers (auth.mode).

Variables

This section is empty.

Functions

This section is empty.

Types

type AccessRule added in v0.10.0

type AccessRule struct {
	AllowedEmails  []string `json:"allowed_emails,omitempty"  koanf:"allowed_emails"`
	AllowedDomains []string `json:"allowed_domains,omitempty" koanf:"allowed_domains"`
	AllowedGroups  []string `json:"allowed_groups,omitempty"  koanf:"allowed_groups"`
}

AccessRule is an email/domain/group allowlist triple. Used for the write-access (admin) tier; the same matching logic as the sign-in allowlist, scoped to a narrower set of identities.

func (AccessRule) IsEmpty added in v0.10.0

func (r AccessRule) IsEmpty() bool

IsEmpty reports whether the rule matches nobody (all three slices empty).

type Auth added in v0.8.0

type Auth struct {
	Enabled bool `json:"enabled" koanf:"enabled"`
	// Mode selects how a request is authenticated when Enabled:
	//   "oidc" (default) — cheshmhayash runs the OIDC login flow itself and
	//                       issues an HMAC-signed session cookie.
	//   "jwt"            — no login flow. Every request must carry an
	//                       `Authorization: Bearer <jwt>` access token minted
	//                       by auth.oidc.issuer (a "builtin oauth" gateway in
	//                       front of cheshmhayash). The token's signature /
	//                       issuer / expiry are verified and its claims drive
	//                       the same allowlist + admin/readonly roles.
	Mode     string       `json:"mode,omitempty"     koanf:"mode"`
	OIDC     AuthOIDC     `json:"oidc"               koanf:"oidc"`
	Access   AuthAccess   `json:"access"             koanf:"access"`
	Session  AuthSession  `json:"session"            koanf:"session"`
	JWT      AuthJWT      `json:"jwt,omitzero"       koanf:"jwt"`
	MCPKeys  []MCPKey     `json:"mcp_keys,omitempty" koanf:"mcp_keys"`
	MCPOAuth AuthMCPOAuth `json:"mcp_oauth,omitzero" koanf:"mcp_oauth"`
	MCPJWT   AuthMCPJWT   `json:"mcp_jwt,omitzero"   koanf:"mcp_jwt"`
}

Auth gates the HTTP API behind OIDC. When Enabled is false the API stays open (backward-compatible default). MCP HTTP is gated by MCPKeys independently: leave the slice empty to keep /mcp open like before.

func (Auth) ModeOrDefault added in v0.13.0

func (a Auth) ModeOrDefault() string

ModeOrDefault returns the configured auth mode lower-cased, defaulting to "oidc" when unset so existing configs keep their cookie-login behaviour.

type AuthAccess added in v0.8.0

type AuthAccess struct {
	AllowedEmails  []string   `json:"allowed_emails,omitempty"  koanf:"allowed_emails"`
	AllowedDomains []string   `json:"allowed_domains,omitempty" koanf:"allowed_domains"`
	AllowedGroups  []string   `json:"allowed_groups,omitempty"  koanf:"allowed_groups"`
	GroupsClaim    string     `json:"groups_claim,omitempty"    koanf:"groups_claim"`
	Admin          AccessRule `json:"admin,omitzero"            koanf:"admin"`
}

AuthAccess is the post-login allowlist. At least one of the three sign-in slices must be populated when auth is enabled — otherwise any account in the IdP can sign in, which is almost never what you want.

The sign-in slices (AllowedEmails/Domains/Groups) decide who may open the dashboard at all; everyone who passes them gets at least read-only access. Admin carries a second, write-access allowlist: a signed-in user who additionally matches it gets the "admin" role (full read + write). When Admin is empty every signed-in user is an admin, which preserves the pre-role behaviour where any allowed account had full access.

type AuthJWT added in v0.13.0

type AuthJWT struct {
	// Audiences, when non-empty, restricts accepted tokens to those whose
	// `aud` carries one of these values (RFC 8707). Empty accepts any token
	// the issuer signed — fine when the gateway is the sole ingress and
	// strips a client-supplied Authorization header.
	Audiences []string `json:"audiences,omitempty" koanf:"audiences"`
}

AuthJWT tunes the "jwt" auth mode (auth.mode = "jwt"), where cheshmhayash validates an access-token JWT presented on every request instead of running its own login flow. The token is verified against auth.oidc.issuer.

type AuthMCPJWT added in v0.15.0

type AuthMCPJWT struct {
	Enabled bool `json:"enabled" koanf:"enabled"`
}

AuthMCPJWT is the third /mcp auth path (besides static mcp_keys and the OIDC-verified mcp_oauth): accept a bearer JWT and read its identity claims WITHOUT verifying the token at all — no signature, issuer, audience, or expiry check. The claims still run through the auth.access allowlists to resolve a role, but anyone who can reach /mcp can forge them, so only enable this when a trusted gateway in front of cheshmhayash has already validated the token and untrusted clients can't hit the endpoint directly.

type AuthMCPOAuth added in v0.11.0

type AuthMCPOAuth struct {
	Enabled bool `json:"enabled" koanf:"enabled"`
	// Resource is the canonical URI of this MCP server (RFC 8707), e.g.
	// "https://cheshmhayash.example.com/mcp". Advertised in the metadata
	// document and used as the default accepted token audience.
	Resource string `json:"resource" koanf:"resource"`
	// AuthorizationServers overrides the metadata's authorization_servers
	// list. Defaults to [auth.oidc.issuer] when empty.
	AuthorizationServers []string `json:"authorization_servers,omitempty" koanf:"authorization_servers"`
	// Audiences is the set of `aud` values accepted on inbound access
	// tokens. Defaults to [Resource] when empty. Keycloak must be configured
	// (audience mapper / client scope) to mint tokens carrying one of these.
	Audiences []string `json:"audiences,omitempty" koanf:"audiences"`
	// SkipAudienceCheck accepts any token the issuer signed, regardless of
	// `aud` (signature, issuer and expiry are still enforced, and the
	// subject still has to pass the access allowlist). This drops the
	// RFC 8707 confused-deputy protection — only set it when the IdP can't
	// mint resource audiences (e.g. a Keycloak client without an audience
	// mapper) and the issuer is trusted for this realm.
	SkipAudienceCheck bool `json:"skip_audience_check,omitempty" koanf:"skip_audience_check"`
}

AuthMCPOAuth turns the /mcp HTTP transport into an OAuth 2.0 resource server per the MCP authorization spec (2025-06-18): the server advertises Protected Resource Metadata (RFC 9728) pointing at the same OIDC issuer as the dashboard, and validates Keycloak-issued access-token JWTs presented as `Authorization: Bearer`. Requires auth.enabled (it reuses the OIDC provider and the auth.access allowlists). Static auth.mcp_keys keep working as a fallback alongside it. Off by default — backward-compatible.

type AuthOIDC added in v0.8.0

type AuthOIDC struct {
	Issuer       string   `json:"issuer"       koanf:"issuer"`
	ClientID     string   `json:"client_id"    koanf:"client_id"`
	ClientSecret string   `json:"-"            koanf:"client_secret"`
	RedirectURL  string   `json:"redirect_url" koanf:"redirect_url"`
	Scopes       []string `json:"scopes"       koanf:"scopes"`
}

AuthOIDC holds the OpenID Connect provider coordinates for the login flow.

type AuthSession added in v0.8.0

type AuthSession struct {
	Secret     string `json:"-"           koanf:"secret"`
	TTLSeconds int    `json:"ttl_seconds" koanf:"ttl_seconds"`
	CookieName string `json:"cookie_name" koanf:"cookie_name"`
	Secure     bool   `json:"secure"      koanf:"secure"`
}

AuthSession configures the HMAC-signed cookie that carries the session.

func (AuthSession) TTL added in v0.8.0

func (a AuthSession) TTL() time.Duration

TTL is the cookie lifetime as a duration. Falls back to 12 h when unset.

type MCPKey added in v0.8.0

type MCPKey struct {
	Name  string `json:"name" koanf:"name"`
	Value string `json:"-"    koanf:"value"`
}

MCPKey is one bearer token accepted on the /mcp HTTP transport. Name is human-readable for log lines / revocation; Value is the secret.

type NATS

type NATS struct {
	Name      string `json:"name"                 koanf:"name"`
	URL       string `json:"url"                  koanf:"url"`
	CredsFile string `json:"creds_file,omitempty" koanf:"creds_file"`
	User      string `json:"user,omitempty"       koanf:"user"`
	// Password is redacted on the startup log; the JSON tag matters only
	// for that single pretty-print.
	Password           string `json:"-"                              koanf:"password"`
	RequestTimeoutMS   int    `json:"request_timeout_ms,omitempty"   koanf:"request_timeout_ms"`
	DiscoveryTimeoutMS int    `json:"discovery_timeout_ms,omitempty" koanf:"discovery_timeout_ms"`
}

NATS describes one configured cluster connection.

func (NATS) DiscoveryTimeout

func (n NATS) DiscoveryTimeout() time.Duration

DiscoveryTimeout is the deadline for multi-responder discovery requests (e.g. SERVER.PING), defaulted when unset.

func (NATS) RequestTimeout

func (n NATS) RequestTimeout() time.Duration

RequestTimeout is the per-request NATS deadline, defaulted when unset.

type Notify added in v0.6.0

type Notify struct {
	Provider string `json:"provider"           koanf:"provider"` // slack | mattermost | matrix
	URL      string `json:"-"                  koanf:"url"`      // redacted in startup log
	Channel  string `json:"channel,omitempty"  koanf:"channel"`
	Username string `json:"username,omitempty" koanf:"username"`
}

Notify describes one outbound chat webhook. The provider field selects the JSON shape and target API.

type Server

type Server struct {
	Host string `json:"host" koanf:"host"`
	Port int    `json:"port" koanf:"port"`
}

Server is the HTTP listener's bind address.

func (Server) Addr

func (s Server) Addr() string

Addr is the host:port the HTTP server binds to.

type Settings

type Settings struct {
	Server Server   `json:"server"           koanf:"server"`
	NATS   []NATS   `json:"nats"             koanf:"nats"`
	Notify []Notify `json:"notify,omitempty" koanf:"notify"`
	Auth   Auth     `json:"auth"             koanf:"auth"`
}

Settings is the fully-resolved runtime configuration (defaults → TOML → env), returned by Load and consumed by main.

func Default added in v0.5.1

func Default() Settings

Default returns the baseline configuration that ships with the binary. Anything left unset in `settings.toml` or `CHESHMHAYASH__*` env vars falls back to these values.

func Load

func Load() (*Settings, error)

Load layers defaults → TOML → env. The returned *Settings is fully validated; callers can use it without further checks.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL