config

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package config loads locksql profiles from the project and user config files, applies defaults, refuses anything that looks like a secret, and computes the security-relevant policy of a profile.

Index

Constants

View Source
const (
	EngineMariaDB  = "mariadb"
	EngineMySQL    = "mysql"
	EnginePostgres = "postgres"
	EngineSQLite   = "sqlite"
)

Supported engines.

View Source
const (
	CredentialsAsk      = "ask"
	CredentialsKeychain = "keychain"
)

Credentials modes.

View Source
const DefaultMaskMode = "redact"

DefaultMaskMode is the mode of a mask rule that sets none.

Variables

This section is empty.

Functions

func ApprovedKey

func ApprovedKey(root, profile string) string

ApprovedKey names the approved-policy file of a profile: <ProjectHash(root)>-<profile>, or user-<profile> for a profile that comes from the user config only (root == "").

func DefaultDetectors

func DefaultDetectors() []string

DefaultDetectors is the detector set used when a profile does not set detectors. National id detectors are opt-in.

func FindProjectRoot

func FindProjectRoot(cwd string) (string, bool)

FindProjectRoot walks up from cwd to the first directory holding .locksql/config.toml.

func Fingerprint

func Fingerprint(p Policy) string

Fingerprint returns the hex sha256 of the policy's canonical JSON. List order does not change the fingerprint.

func ParseProfiles added in v0.1.2

func ParseProfiles(data []byte, name, baseDir string) (map[string]Profile, error)

ParseProfiles decodes and validates config data. name labels errors. Relative sqlite paths are resolved against baseDir. Errors never quote config values that could be secrets.

func ProjectHash

func ProjectHash(root string) string

ProjectHash returns the first 8 hex digits of sha256 of the absolute, cleaned project root.

func ProjectKey

func ProjectKey(cwd string) string

ProjectKey names the project of cwd in socket paths: ProjectHash of the project root, or "user" when cwd is outside any project (profiles from the user config only). The console and its clients must agree on it.

func SaveApproved

func SaveApproved(stateDir, key string, p Policy) error

SaveApproved atomically writes the policy to <stateDir>/locksql/approved/<key>.json with mode 0600.

func StateDir

func StateDir() (string, error)

StateDir returns the user state directory (without the locksql suffix): $XDG_STATE_HOME or ~/.local/state on Linux and other Unix systems, and os.UserConfigDir() on macOS.

func UserConfigPath added in v0.1.2

func UserConfigPath() (string, error)

UserConfigPath returns <user config dir>/locksql/config.toml.

Types

type Change

type Change struct {
	Field    string
	Old, New string
	Loosens  bool
}

Change is one difference between two policies. For list fields (detectors, pii.mask, pii.allow) each added or removed element is its own Change, with Old empty for an addition and New empty for a removal.

func Diff

func Diff(approved, current Policy) []Change

Diff lists the changes from approved to current and marks each loosening (spec section 4): a higher tier, production true→false, a larger limit (0 means unlimited), a removed PII rule or detector, an added allow rule, any change of engine, host, port, path, database or user, and a credentials mode other than ask.

type Config

type Config struct {
	// ProjectRoot is the directory holding .locksql/config.toml, or "" when
	// no project config was found.
	ProjectRoot string
	Profiles    map[string]Profile
}

Config is the merged set of profiles visible from a working directory.

func Load

func Load(cwd string) (*Config, error)

Load reads the project config (found by walking up from cwd) and the user config (<user config dir>/locksql/config.toml). On a profile name present in both, the project profile wins as a whole.

func LoadFrom

func LoadFrom(cwd, userConfigPath string) (*Config, error)

LoadFrom is Load with an explicit user config path ("" for none). A missing user config file is not an error.

type Limits

type Limits struct {
	StatementTimeout  time.Duration `toml:"statement_timeout" json:"statement_timeout"`
	ExplainRowsWarn   int64         `toml:"explain_rows_warn" json:"explain_rows_warn"`
	ExplainRowsRefuse int64         `toml:"explain_rows_refuse" json:"explain_rows_refuse"`
	MaxRows           int           `toml:"max_rows" json:"max_rows"`
	MaxCellChars      int           `toml:"max_cell_chars" json:"max_cell_chars"`
	MaxOutputBytes    int           `toml:"max_output_bytes" json:"max_output_bytes"`
	// ExplainCostRefuse refuses a plan whose total cost, in the engine's
	// own units, is above it; 0 disables the check. Engines without a cost
	// (SQLite) are not checked.
	ExplainCostRefuse float64 `toml:"explain_cost_refuse" json:"explain_cost_refuse,omitempty"`
	// KAnonymity is the smallest number of rows a PII filter, a grouping
	// on a PII column or an aggregate of one may cover.
	KAnonymity int `toml:"k_anonymity" json:"k_anonymity,omitempty"`
	// ReferenceProbe is how many distinct cells of one result the agent may
	// filter on, one statement each, before the console warns of equality
	// probing; raising it is a loosening.
	ReferenceProbe int `toml:"reference_probe" json:"reference_probe,omitempty"`
}

Limits bound the cost and size of one statement.

func DefaultLimits

func DefaultLimits(production bool) Limits

DefaultLimits returns the limits applied to unset (zero) limit fields.

type Policy

type Policy struct {
	Profile  Profile  `json:"profile"`
	PIIMask  []string `json:"pii_mask"`  // sorted column patterns
	PIIAllow []string `json:"pii_allow"` // sorted column patterns
	// PIIModes maps a mask pattern to its mode when it is not the default
	// (redact): partial or email.
	PIIModes map[string]string `json:"pii_modes,omitempty"`
}

Policy is the security-relevant view of one profile plus its PII rules. The console compares the current policy with the last approved one and asks the human before applying any loosening.

func LoadApproved

func LoadApproved(stateDir, key string) (*Policy, error)

LoadApproved reads <stateDir>/locksql/approved/<key>.json. When no policy was approved yet, the error wraps fs.ErrNotExist.

func NewPolicy

func NewPolicy(p Profile, mask, allow []string) Policy

NewPolicy builds a policy with sorted, de-duplicated PII lists.

func (Policy) WithModes

func (p Policy) WithModes(m map[string]string) Policy

WithModes returns p with the mask modes m (pattern -> mode).

type Profile

type Profile struct {
	Name        string   `json:"name"`
	Engine      string   `json:"engine"`
	Host        string   `json:"host"`
	Path        string   `json:"path"`
	User        string   `json:"user"`
	Database    string   `json:"database"`
	Credentials string   `json:"credentials"`
	Port        int      `json:"port"`
	Tier        Tier     `json:"tier"`
	Production  bool     `json:"production"`
	Detectors   []string `json:"detectors"`
	Limits      Limits   `json:"limits"`
	// CredentialsTTL makes the console ask for the secret again (and
	// reconnect) once the connection is that old; 0 keeps it for the
	// session. It suits short-lived secrets from a vault.
	CredentialsTTL time.Duration `json:"credentials_ttl,omitempty"`
}

Profile is one named database target with its policy. It never holds a secret.

type Tier

type Tier int

Tier is the highest statement class a profile may run. The order is TierRead < TierWrite < TierDDL < TierAdmin.

const (
	TierRead Tier = iota
	TierWrite
	TierDDL
	TierAdmin
)

Tiers, in increasing order of privilege.

func ParseTier

func ParseTier(s string) (Tier, error)

ParseTier parses "read", "write", "ddl" or "admin".

func (Tier) MarshalText

func (t Tier) MarshalText() ([]byte, error)

MarshalText encodes the tier by name.

func (Tier) String

func (t Tier) String() string

func (*Tier) UnmarshalText

func (t *Tier) UnmarshalText(b []byte) error

UnmarshalText decodes a tier name.

Jump to

Keyboard shortcuts

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