uniqueness

package
v0.44.1 Latest Latest
Warning

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

Go to latest
Published: Sep 23, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package uniqueness implements the per-environment value-duplication engine: flattening per-env input maps to dot-paths, classifying which leaves look like identifiers, detecting duplicates and cross-env token leakage, and evaluating both against reviewed `allow` exceptions. It is a generic, config-driven port of a proven Python prototype (see docs/DESIGN.md).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AllowMatches

func AllowMatches(a AllowRule, v Violation, now time.Time) bool

AllowMatches reports whether allow rule a justifies violation v as of now: their Unit is identical, a's Key equals v's Key exactly or as a filepath.Match glob against it, a's Envs is a superset of v's Envs, and a is not expired. Mirrors the Python prototype's entry_matches.

func BoundaryTokenPattern

func BoundaryTokenPattern(tok string) *regexp.Regexp

BoundaryTokenPattern returns a compiled RE2 regexp matching tok as a whole token: not flanked by an alphanumeric character. E.g. the token "acme-dev" matches inside "acme-dev.example.com" but not inside "acme-development". RE2 has no lookaround, so this consumes the boundary character (start/end of string or a non-alphanumeric rune) rather than asserting it via zero-width lookaround, mirroring the Python prototype's _token_in helper. Shared by IsIdentifier's env-token folding and (per Task 5) the env-token leak detector, so both use identical boundary semantics.

func DefaultKeyPatterns

func DefaultKeyPatterns() []*regexp.Regexp

DefaultKeyPatterns returns the built-in, generic key-name patterns: a leaf whose last dot-segment matches one of these is identifier-like by name alone (value-shape still gates via QtySuffixes/empty/bool checks in IsIdentifier).

func DefaultQuantitySuffixes

func DefaultQuantitySuffixes() []string

DefaultQuantitySuffixes returns the built-in leaf-key suffixes that denote quantities, durations, or counts — never identifiers even when the value is a long number (e.g. kills jwt_expiration_ms=86400000 false positives).

func DefaultValuePatterns

func DefaultValuePatterns() []*regexp.Regexp

DefaultValuePatterns returns the built-in, generic value-shape patterns that mark a leaf as identifier-like regardless of its key name: a UUID, an http(s) URL, a generic dotted hostname with a TLD (NOT any specific domain), and a long opaque numeric string (e.g. a phone/account/system id). Deliberately does NOT match semver, bare enums, or booleans.

func DeriveTokensAndSegs

func DeriveTokensAndSegs(envs []string, template string, extraTokens map[string][]string, extraSegs []string) (map[string][]string, map[string]bool)

DeriveTokensAndSegs computes, per environment, the set of tokens that identify it in a config value (the {env}-templated project name if template is non-empty, plus the bare env name, plus any extraTokens for that env), and the full set of env-scoped segment names (lowercased env names, lowercased tokens, and lowercased extraSegs) used by IsEnvScoped.

func Flatten

func Flatten(inputs map[string]any) map[string]any

Flatten collapses a nested map (as decoded from YAML/JSON — nested map[string]any, []any, and scalars) into a single-level map keyed by dot-joined paths. A []any value becomes a List sentinel with each element stringified (via fmt.Sprint); any other scalar (including bool, and nil) passes through unchanged. It mirrors the Python prototype's `flatten`, which collapses lists to a ("__list__", tuple(str(x)...)) sentinel.

func Partition

func Partition(vios []Violation, allows []AllowRule, now time.Time) (unjustified []Violation, stale []AllowRule)

Partition splits violations against the given allow rules as of now: only SeverityViolation entries require justification (report-only violations never need an allow and are never unjustified). Expired allows are dropped from consideration entirely first — they neither justify a violation nor count as stale. Among the remaining active allows, a violation with no matching active allow is unjustified; an active allow that matches zero violations is stale. Mirrors the Python prototype's partition (first-matching-allow semantics).

Types

type AllowRule

type AllowRule struct {
	Unit    string
	Key     string
	Envs    []string
	Reason  string
	Expires string
}

AllowRule is one reviewed exception (an `allow {}` config block): it justifies a violation for a given unit/key across a set of envs, with a mandatory reason and an optional expiry after which it no longer applies.

type Classifier

type Classifier struct {
	ValPats     []*regexp.Regexp
	KeyPats     []*regexp.Regexp
	QtySuffixes []string
	EnvTokens   map[string][]string
	ScopedSegs  map[string]bool
	// contains filtered or unexported fields
}

Classifier decides whether a flattened (key, value) leaf is identifier-shaped and whether a key is env-scoped fan-out config that should be skipped entirely. ValPats/KeyPats/QtySuffixes are typically the generic Default* built-ins; EnvTokens/ScopedSegs are the per-repo derived tokens/segments from DeriveTokensAndSegs.

tokenPats caches the compiled EnvTokens boundary patterns (see BoundaryTokenPattern). It is unexported and left zero (nil) by a plain struct literal — IsIdentifier still works in that case, falling back to compiling EnvTokens on the fly, just without the cache. Use NewClassifier to get the patterns precompiled once instead of on every IsIdentifier call.

func NewClassifier

func NewClassifier(valPats, keyPats []*regexp.Regexp, qtySuffixes []string, envTokens map[string][]string, scopedSegs map[string]bool) Classifier

NewClassifier builds a Classifier with its EnvTokens boundary patterns precompiled once (see BoundaryTokenPattern), instead of recompiling them on every IsIdentifier call — IsIdentifier is called once per flattened leaf per unit, so per-call recompilation over all EnvTokens is a real, easily avoidable cost. Prefer this over a bare struct literal whenever the Classifier will be reused across many IsIdentifier calls (e.g. by a detector, as in Task 5).

func (Classifier) IsEnvScoped

func (c Classifier) IsEnvScoped(key string) bool

IsEnvScoped reports whether any lowercased dot-segment of key is a known env-scoped segment (an env name, a derived env token, or a repo-configured extra scoped segment) — i.e. the key is fan-out config keyed by environment, not a per-instance value the duplication/token detectors should look at.

func (Classifier) IsIdentifier

func (c Classifier) IsIdentifier(key string, value any) bool

IsIdentifier ports the Python prototype's is_identifier: bool, nil, and empty-string values are never identifiers. A List value is an identifier iff any element is (checked recursively under the same key). Otherwise, if the key's last dot-segment ends with a quantity suffix, it is never an identifier; else it is an identifier if that leaf matches a KeyPat, or the stringified value matches a ValPat, or a derived env token (from EnvTokens, boundary-safe) appears in the stringified value.

type Kind

type Kind string

Kind identifies which detector produced a Violation.

const (
	KindDuplicate Kind = "duplicate"
	KindEnvToken  Kind = "env-token"
)

type List

type List struct {
	Elems []string
}

List is the sentinel Flatten emits for a []any leaf: its elements stringified, in original order. It stands in for the Python prototype's ("__list__", tuple(...)) tuple sentinel.

type Report

type Report struct {
	Unjustified []Violation
	Stale       []AllowRule
	ReportOnly  []Violation
}

Report is the outcome of evaluating all units: violations left unjustified (command should fail), allow rules that matched nothing (stale — should be removed), and violations that are report-only (never fail the command but are still worth surfacing).

func Evaluate

func Evaluate(cfg *config.EnvUniquenessConfig, units []Unit, now time.Time) (Report, error)

Evaluate runs the full per-environment-value-duplication lint for cfg over units as of now: it resolves each discovered env's Tier (either from declared cfg.Environments blocks, or — when cfg.Source.TierInput is set — from that flattened input leaf, read consistently across all units), derives the repo's env tokens/scoped segments, builds a Classifier, collects every duplicate and env-token Violation across all units, and partitions them against cfg.Allows as of now. Mirrors the Python prototype's evaluate.

type Severity

type Severity string

Severity classifies a Violation's blocking-ness: "violation" fails the command, "report-only" is surfaced but never fails it.

const (
	SeverityViolation  Severity = "violation"
	SeverityReportOnly Severity = "report-only"
)

type Tier

type Tier string

Tier is an environment's protection class (e.g. "prod", "nonprod"). It is declared per environment (or resolved from data) and drives whether a cross-boundary duplicate is a blocking violation or report-only.

type Unit

type Unit struct {
	ID     string
	Envs   []string
	Inputs map[string]map[string]any
}

Unit is one lintable thing: a stack/component instance with a stable ID and its flattened per-environment inputs. Inputs[env][dotpath] holds the flattened leaf value for that environment (see Flatten).

func LoadUnits

func LoadUnits(root string, src config.SourceBlock) ([]Unit, error)

LoadUnits discovers Catalyst instance manifests under root matching src.Glob, parses each as YAML, and builds one Unit per file.

src.Glob has the "<prefix>/**/<suffix-glob>" shape (default "components/**/instances/*.tm.yml"); Go's filepath.Glob doesn't support "**", so this walks root with filepath.WalkDir instead, keeping any file whose root-relative path starts with the literal prefix directory and whose trailing path segments match the suffix glob (matched with filepath.Match against just the tail — so arbitrary directories may sit between the prefix and the suffix, honoring the "**").

For each matched file: src.EnvironmentsPath (default "environments") navigates to a map keyed by environment name; for each environment, src.InputsPath (default "inputs") navigates to that environment's inputs, which are flattened (see Flatten) into Unit.Inputs[env]. Unit.ID is the file's root-relative path with the prefix and ".tm.yml" suffix trimmed (e.g. "components/x/api/instances/api.tm.yml" -> "x/api/instances/api"). Unit.Envs is the sorted set of environment names found.

Tier-leaf stripping (e.g. dropping a tier_class input before detection) is NOT this function's concern: any such field is parsed as an ordinary leaf, same as every other input. That's Evaluate's job.

A matched file that can't be parsed, or whose environments block is present but malformed (not a map, bad inputs shape), is a hard error (fail loud). A matched file that lacks the environments block ENTIRELY is skipped, not an error — it's a single-env / non-comparable instance (e.g. a per-env-file BundleInstance with only top-level inputs) with no cross-env values to lint.

type Violation

type Violation struct {
	Unit     string
	Key      string
	Value    any
	Envs     []string
	Kind     Kind
	Severity Severity
}

Violation is one flagged finding: a unit/key pair whose value is duplicated across (or leaks a token into) the listed envs.

func FindDuplicates

func FindDuplicates(u Unit, tierOf map[string]Tier, protected Tier, c Classifier) []Violation

FindDuplicates detects, within a single Unit, dot-path keys whose leaf value is identical across two or more of the unit's environments — where that value is identifier-shaped (per Classifier.IsIdentifier) and the key itself is not env-scoped fan-out config (per Classifier.IsEnvScoped).

Severity is tier-aware: for each equal-value group of ≥2 envs, the tier of an env is tierOf[env] if present, else protected (fail-closed — an env missing from tierOf is always treated as protected, never as an escape hatch). A group is a blocking SeverityViolation if its tiers include both protected and some non-protected tier; a group confined to a single tier (all protected, or all some other tier) is SeverityReportOnly.

Keys are iterated in sorted order, and each Violation's Envs are sorted, for deterministic output. This ports the Python prototype's find_duplicate_violations plus its _tier fail-closed helper.

func FindEnvTokens

func FindEnvTokens(u Unit, c Classifier) []Violation

FindEnvTokens detects, within a single Unit, a leaf value in one env that embeds another env's identifying token — e.g. a dev URL accidentally hardcoded into prod's config. For each env E (in sorted order) and each of its leaves (sorted by key, skipping any key for which Classifier.IsEnvScoped is true), the leaf's value is turned into candidate strings: a non-empty scalar string yields itself; a List yields its non-empty elements; anything else (bool, number, empty string, nil) is skipped entirely — it can never leak a token. If any candidate contains, as a whole token (see BoundaryTokenPattern), any token belonging to a *foreign* env (any env F != E in c.EnvTokens), exactly one Violation is emitted for that leaf and scanning moves on to the next leaf — at most one violation per leaf, regardless of how many foreign tokens or candidates matched.

This ports the Python prototype's find_env_token_violations plus its _token_in boundary-safe helper (here, BoundaryTokenPattern).

Jump to

Keyboard shortcuts

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