denial

package
v1.0.215 Latest Latest
Warning

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

Go to latest
Published: Aug 24, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package denial implements the attacker-mintable denial lane (MCP-EVENT-007): pre-queue admission control and attacker-rate-independent coalescing for authentication-failure and authorization-denial events, so N equivalent denials in one bucket/window cost O(1) durable records. The aggregator holds bounded in-memory aggregates keyed by capability/listener × normalized source bucket × denial reason × bounded time window (plus verified tenant/principal only where identity exists — never invented before identity). It NEVER commits to disk itself and NEVER consumes the P-CRIT reserve; the manager commits the flushed aggregates into P-DEN and, on failure, records the DISTINCT denial-loss counter and enters denial-lane-degraded. A denial-lane failure never blocks authenticated work and never enters critical-durability-degraded.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NormalizeSource

func NormalizeSource(raw string) string

NormalizeSource collapses a raw source address into a stable, bounded bucket token, following the repository precedent for client-evidence tokens: an IPv6 address is collapsed to its /64 prefix (so per-host churn within a /64 folds into one bucket), an IPv4 address is kept raw (a /24 would over-collapse a NAT fleet), and a non-IP source is sanitized and bounded. The result is a bucket key, never a raw unbounded source text.

Types

type Aggregator

type Aggregator struct {
	// contains filtered or unexported fields
}

Aggregator coalesces denial observations into bounded O(1) aggregates.

func NewAggregator

func NewAggregator(cfg Config) *Aggregator

NewAggregator builds an aggregator. It does not start any goroutine; the manager drives Flush on a bounded cadence.

func (*Aggregator) Flush

func (a *Aggregator) Flush(now time.Time, force bool) []*model.Event

Flush returns the denial-aggregate events whose window has closed (windowIdx < current window), removing them from the map. force=true flushes every aggregate (used at shutdown). The manager commits the returned events into P-DEN; a commit failure is the manager's denial-loss/degraded concern, not the aggregator's — a returned event is already coalesced O(1).

func (*Aggregator) Observe

func (a *Aggregator) Observe(o Observation) bool

Observe records one denial. It is O(1) and never blocks. It returns true when the denial was folded into an aggregate, and false when a cardinality bound dropped it (the triggering request is still denied by the caller regardless — admission to the aggregate is not admission of the request). A dropped observation is counted so the manager can surface denial-lane pressure.

func (*Aggregator) Stats

func (a *Aggregator) Stats() Stats

Stats returns a safe snapshot.

type Config

type Config struct {
	Capability   model.Capability
	NodeID       string
	Window       time.Duration
	MaxBuckets   int
	MaxPerSource int
	// IDGen mints a safe, unpredictable, prefixed id (evt_/rpl_/cor_). Injected so
	// tests are deterministic and production uses crypto/rand.
	IDGen func(prefix string) string
}

Config parameterises the aggregator. Bounds are validated event limits threaded through by the manager. Window is the coalescing window; MaxBuckets and MaxPerSource bound aggregation-key cardinality so an attacker cannot create an unbounded number of keys.

type Observation

type Observation struct {
	Now       time.Time
	Listener  string
	Source    string // raw source; normalized internally
	Reason    string
	Tenant    string // "" before identity exists
	Principal string // "" before identity exists
}

Observation is one denial event fed to the aggregator BEFORE it can occupy any shared queue. Tenant and Principal are set ONLY when verified identity exists (the authenticated-but-unauthorized case); for a pre-authentication failure they are empty and no tenant is ever invented from an attacker hint.

type Stats

type Stats struct {
	ActiveBuckets int
	Admitted      uint64
	Dropped       uint64
}

Stats is a safe snapshot of the aggregator.

Jump to

Keyboard shortcuts

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