attention

package
v0.9.2 Latest Latest
Warning

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

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

Documentation

Overview

Package attention builds the list of things an operator should look at right now, shared by the CLI and the MCP server.

Index

Constants

View Source
const (
	Critical = "critical"
	Warning  = "warning"
	Info     = "info"
)

Severity levels, critical first. Info is for resolved items that need no action, such as a login that expired.

View Source
const (
	KindNodeReenroll            = "node_reenroll"
	KindNodeFailure             = "node_failure"
	KindDeviceLogin             = "device_login"
	KindDeviceLoginResolved     = "device_login_resolved"
	KindApproval                = "approval"
	KindTokenExpiring           = "token_expiring"       //nolint:gosec // item kind name, not a credential
	KindTokenExpired            = "token_expired"        //nolint:gosec // item kind name, not a credential
	KindTokenExpiredInUse       = "token_expired_in_use" //nolint:gosec // item kind name, not a credential
	KindDataCopy                = "data_copy"
	KindBackupOverdue           = "backup_overdue"
	KindInvites                 = "invites"
	KindLoginCode               = "login_code"
	KindLoginApproval           = "login_approval"
	KindLoginAnomaly            = "login_anomaly"
	KindAccountFlagged          = "account_flagged"
	KindTokenUnused             = "token_unused" //nolint:gosec // item kind name, not a credential
	KindDBSecurityUpdates       = "db_security_updates"
	KindDBEOL                   = "db_eol"
	KindDBUpgradeFailed         = "db_upgrade_failed"
	KindDockerGuard             = "docker_guard"
	KindUpgradeBlocked          = "upgrade_blocked"
	KindResourceAdvice          = "resource_advice"
	KindSecretRotationDue       = "secret_rotation_due"
	KindSecretRotationFail      = "secret_rotation_failed"
	KindQuotaNearLimit          = "quota_near_limit"
	KindAccessReviewOverdue     = "access_review_overdue"
	KindMaintenanceLong         = "maintenance_long"
	KindGitHostUnreachable      = "git_host_unreachable"
	KindFirewallAttackSuggested = "firewall_attack_suggested"
	KindNodeCapacity            = "node_capacity"
	KindStackDrift              = "stack_drift"
	KindAdvisoryMatch           = "advisory_match"
)

Item kinds that block on a person, ranked ahead of other items of the same severity.

View Source
const (
	ClassIncident       = "incident"
	ClassRecommendation = "recommendation"
)

Class separates things that are broken or about to break from setup and hardening advice. Only incidents belong on the dashboard and the header chip; recommendations live in the notification centre.

View Source
const (
	TierCritical     = "critical"
	TierNeedsAction  = "needs_action"
	TierAdvisory     = "advisory"
	TierAutoResolved = "auto_resolved"
)

Tier is how loudly an item is shown. Only critical and needs_action count toward the header chip.

View Source
const (
	GroupDockerAccess = "docker_access"
	GroupDisk         = "disk"
	GroupCertificates = "certificates"
	GroupNodes        = "nodes"
	GroupTokens       = "tokens"
	GroupBackups      = "backups"
	GroupExposure     = "exposure"
)

Group keys for rows that share one root cause.

View Source
const DockerGuardWouldDenyHigh = "would-deny:high"

DockerGuardWouldDenyHigh prefixes the guard item subject when the audit window holds a would-be denial for a rule that means host-level power.

View Source
const EnvShortLivedCert = "APP_ATTENTION_SHORT_LIVED_CERT"

EnvShortLivedCert tunes how short a certificate lifetime counts as auto-renewed internal issuance that never needs attention.

View Source
const MaxErrorText = 200

MaxErrorText bounds an agent-reported error shown in an item.

Variables

This section is empty.

Functions

func Assess

func Assess(s Signal) (tier, group string)

Assess returns the tier and group of one signal; tier is empty for a doctor row that is not warn or fail.

func CertExpiryClass

func CertExpiryClass(f CertFacts, shortLived time.Duration) string

CertExpiryClass returns ClassIncident when the certificate's expiry needs an operator, else "". Internal-CA, proxy-owned and unrouted certificates never raise one, and an auto-renewing ACME certificate only does once it expired, its renewal stalled or failed, or it is inside the failure window. Uploaded certificates do not renew themselves, so they count as soon as they enter the warning window.

func ClassOf

func ClassOf(kind, subject string) string

ClassOf classifies one item. An enforce-mode guard denial, a high-risk audit finding and every other unlisted kind is an incident.

func CountsTowardHeader

func CountsTowardHeader(tier string) bool

CountsTowardHeader is the header count rule.

func DoctorClass

func DoctorClass(code, status string) string

DoctorClass classifies a doctor check that is not ok. A failed check is always an incident.

func HeaderCount

func HeaderCount(items []Item) int

HeaderCount is how many items the header chip shows.

func SafeErrorText

func SafeErrorText(s string) string

SafeErrorText bounds and cleans text an agent reported. Anything that looks like key or certificate material is replaced entirely.

func ShortLivedCertLimit

func ShortLivedCertLimit() time.Duration

ShortLivedCertLimit reads APP_ATTENTION_SHORT_LIVED_CERT.

Types

type CertFacts

type CertFacts struct {
	Issuer    string
	Source    string
	TLSOwner  string
	Status    string
	Renewal   string
	NotBefore time.Time
	NotAfter  time.Time
	// Routed is false for a certificate whose domain no app or site serves.
	Routed bool
	// RenewalFailed is true when the CA refused the last renewal; NearExpiry
	// when an auto-renewed certificate is inside the failure window.
	RenewalFailed bool
	NearExpiry    bool
}

CertFacts is what the expiry rules decide from.

type Input

type Input struct {
	Apps    []apiclient.AppStatusEntry
	Nodes   []apiclient.NodeResource
	Certs   []apiclient.CertificateResource
	Doctor  apiclient.SystemDoctorResource
	Failed  []apiclient.FailedDeployResource
	Status  apiclient.SystemStatusResource
	Updates apiclient.UpdatesResource
	// Devices are CLI logins waiting for approval, Approvals are pending
	// deploy approvals. Now defaults to time.Now when zero.
	Devices   []apiclient.DevicePendingLogin
	Approvals []apiclient.DeployApprovalResource
	// Resolved are recent expired or denied CLI logins the caller has not
	// dismissed. Feed holds the server-built items for tokens, data copies,
	// backups and invitations, already limited to what the caller may see.
	Resolved []apiclient.DeviceActivity
	Feed     []apiclient.AttentionFeedItem
	Now      time.Time
}

Input is everything Build reads; any field may be zero when its endpoint was unavailable.

type Item

type Item struct {
	Severity string `json:"severity"`
	Kind     string `json:"kind"`
	Subject  string `json:"subject"`
	Detail   string `json:"detail"`
	// Fixable is set on deploy and app items whose diagnosis carries a
	// one-click fix.
	Fixable bool `json:"fixable,omitempty"`
	// ID is stable across polls for the same condition. Title is one plain
	// line, Action the next step, Link a dashboard path to do it in.
	ID     string            `json:"id"`
	Title  string            `json:"title"`
	Action string            `json:"action"`
	Link   string            `json:"link"`
	Params map[string]string `json:"params,omitempty"`
	// Class is ClassIncident or ClassRecommendation.
	Class string `json:"class"`
	// Tier is one of the Tier constants and Group the root cause key; both
	// come from Assess.
	Tier  string `json:"tier,omitempty"`
	Group string `json:"group,omitempty"`
}

Item is one thing that needs an operator's attention.

func Build

func Build(in Input) []Item

Build mirrors web/src/lib/attention.ts: disk pressure, failing apps, recent failed deploys, offline nodes, bad certificates, and doctor warnings or failures, critical first.

func Collect

func Collect(ctx context.Context, client *apiclient.Client) ([]Item, error)

Collect gathers every source the caller's token may read and returns the attention items. A source that fails or is forbidden drops only its own items; it fails only when no source answered at all.

func FilterSilenced

func FilterSilenced(items []Item, silences []apiclient.IssueSilenceResource, now time.Time) []Item

FilterSilenced drops items an active silence covers.

func NewItem

func NewItem(severity, kind, subject, detail string) Item

NewItem is newItem for callers outside this package, such as the server's attention feed.

type Signal

type Signal struct {
	Kind     string
	Subject  string
	Severity string
	Status   string
	Class    string
	Message  string
}

Signal is everything the tier and group mapping reads. For a doctor row Kind is the row code and Status is ok, warn or fail; for a feed item Kind is the item kind and Severity is critical, warning or info.

Jump to

Keyboard shortcuts

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