judgment

package
v0.1.8 Latest Latest
Warning

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

Go to latest
Published: Aug 15, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package judgment is the AI "analysis brain" primitive: a propose→verify→confirm CLAIM about a subject (a finding, component, vulnerability, or the engagement), evidence-gated and hash-chainable, that generalizes the exploitation gate. It is pure (stdlib + shared + the shared verdict value type – NOT finding, R1): a Judgment never imports the Finding aggregate. The proposing agent can only PROPOSE (score 0); a DISTINCT verifier's sealed verdict (gated capabilities) or a human's acceptance (ungated) is the only thing that confirms it .

Index

Constants

View Source
const (
	RuleRuntimeReachableExposed  = "promotion.escalate.runtime_reachable_exposed"
	RuleDeterministicUnreachable = "promotion.deescalate.deterministic_unreachable"
	RuleUncertainCorroboration   = "promotion.review.uncertain_corroboration"
	RuleCorroboratingSignalLoss  = "promotion.deescalate.corroborating_signal_loss"
)

Stable promotion rule identifiers. These constants are the canonical source of truth; the promotion catalog in internal/domain/promotion reuses them to avoid duplicated string vocabularies across domain packages.

View Source
const (
	ProofActorCallgraphScan    = "system:callgraph-scan"
	ProofActorCallgraphEngine  = "system:callgraph-engine"
	ProofActorJSSymbolScan     = "system:jssymbol-scan"
	ProofActorJSSymbolEngine   = "system:jssymbol-engine"
	ProofActorJSImportScan     = "system:jsimport-scan"
	ProofActorJSImportEngine   = "system:jsimport-engine"
	ProofActorPyImportScan     = "system:pyimport-scan"
	ProofActorPyImportEngine   = "system:pyimport-engine"
	ProofActorRustImportScan   = "system:rustimport-scan"
	ProofActorRustImportEngine = "system:rustimport-engine"
	ProofActorPHPImportScan    = "system:phpimport-scan"
	ProofActorPHPImportEngine  = "system:phpimport-engine"
	ProofActorRubyImportScan   = "system:rubyimport-scan"
	ProofActorRubyImportEngine = "system:rubyimport-engine"
)

Reserved deterministic reachability proof identities. These are domain provenance vocabulary; use cases may mint claims with them but cannot define new proof engines.

Variables

This section is empty.

Functions

func IsDeterministicReachabilityProof added in v0.1.8

func IsDeterministicReachabilityProof(tier ReachabilityTier, proposer, verifier string) bool

IsDeterministicReachabilityProof reports whether the distinct reserved identities prove the supplied reachability tier. Unknown identities fail closed.

func MarshalClaim

func MarshalClaim(c Claim) ([]byte, error)

MarshalClaim encodes a Claim as a discriminated envelope. It requires a non-nil claim with a known capability; field-level validity is the caller's job (New / UnmarshalClaim enforce it).

Types

type Capability

type Capability string

Capability is the CLOSED vocabulary of analysis brains – never an LLM-supplied string. Add one (a const + a Gated case + a concrete Claim type + UnmarshalClaim registration) with its epic.

const (
	CapReachability     Capability = "reachability"      // gated
	CapSAST             Capability = "sast"              // gated
	CapDAST             Capability = "dast"              // gated
	CapCritique         Capability = "critique"          // gated (adversarial refutation of a finding)
	CapRiskNarrative    Capability = "risk_narrative"    // NOT gated (explains, doesn't prove)
	CapThreat           Capability = "threat"            // gated (STRIDE threat over the model, human-ratified)
	CapCorrelation      Capability = "correlation"       // NOT gated (a cross-check disagreement; human-acknowledged, never auto-resolved)
	CapPromotion        Capability = "promotion"         // gated (cross-pillar priority change, distinct-verifier only)
	CapVexJustification Capability = "vex_justification" // gated (AI-proposed OpenVEX not_affected justification, human-ratified)
)

func (Capability) Gated

func (c Capability) Gated() bool

Gated reports whether a verdict gates this capability's publishability (R2). Adversarially- refutable capabilities (reachability/sast/critique/threat/promotion/vex_justification) are gated: publishable only with a sealed verdict >= EvidenceThreshold. Descriptive ones (risk_narrative; correlation – a deterministic cross-check disagreement) have no "refuted at 75" semantics; they are human-accepted, not score-gated.

func (Capability) Valid

func (c Capability) Valid() bool

Valid reports whether c is a known capability.

type Claim

type Claim interface {
	Capability() Capability
	Validate() error
}

Claim is the TYPED, capability-discriminated payload of a Judgment. It is NEVER free prose report templates render its fields; the model's rationale lives only in sealed evidence. Each capability has one concrete Claim type; the JSON envelope carries the discriminant so a stored claim decodes FAIL-CLOSED on an unknown capability or a body that doesn't match its discriminant – no free-text passthrough can reach a deliverable.

func UnmarshalClaim

func UnmarshalClaim(data []byte) (Claim, error)

UnmarshalClaim decodes a discriminated envelope into the concrete Claim for its capability, FAIL-CLOSED: an unknown/unregistered capability, a body carrying unknown fields, a body whose reported capability disagrees with the envelope, or a body that fails Validate is all rejected – never a free-text passthrough.

type CorrelationClaim

type CorrelationClaim struct {
	Reporters []string `json:"reporters"` // sources that reported the vuln (the minter supplies them sorted+distinct)
	Missing   []string `json:"missing"`   // run sources that did NOT report it (minter-sorted+distinct; Validate requires non-empty)
}

CorrelationClaim is a cross-check DISAGREEMENT: on a vulnerability, which detection sources reported it (Reporters) and which RAN but did not (Missing). It is the deterministic, descriptive record that a human acknowledges – NEVER auto-resolved (the disagreement is itself the signal). Both lists are source-name tokens (no prose); Missing is non-empty by construction (an agreed vuln is not a claim).

func (CorrelationClaim) Capability

func (CorrelationClaim) Capability() Capability

Capability identifies this claim's brain.

func (CorrelationClaim) Validate

func (c CorrelationClaim) Validate() error

Validate enforces a real disagreement: at least one reporter and at least one missing source, each a bounded source-name token (never prose). A claim with nothing missing is not a disagreement.

type CritiqueClaim

type CritiqueClaim struct {
	Verdict    CritiqueVerdict `json:"verdict"`
	Driver     string          `json:"driver"` // closed token, e.g. "not_reachable", "version_mismatch", "false_match"
	Confidence int             `json:"confidence"`
}

CritiqueClaim is the typed result of an adversarial critique: an attempt to REFUTE a finding, with a STRUCTURED driver (the refutation category – never free prose) and a confidence. A confirmed "refuted" critique flags the finding as suspected-FP for a human; it never auto-suppresses (fail-safe – a wrong critique cannot publish a falsehood).

func (CritiqueClaim) Capability

func (CritiqueClaim) Capability() Capability

Capability identifies this claim's brain.

func (CritiqueClaim) Validate

func (c CritiqueClaim) Validate() error

Validate enforces the closed verdict vocabulary, the driver token grammar, and a 0..100 confidence.

type CritiqueVerdict

type CritiqueVerdict string

CritiqueVerdict is the closed adversarial verdict on a finding: does it survive refutation?

const (
	CritiqueRefuted   CritiqueVerdict = "refuted"   // the finding does not hold – a suspected false positive
	CritiqueSound     CritiqueVerdict = "sound"     // the finding survives adversarial review
	CritiqueUncertain CritiqueVerdict = "uncertain" // inconclusive
)

func (CritiqueVerdict) Valid

func (v CritiqueVerdict) Valid() bool

Valid reports whether v is a known critique verdict (fail-closed).

type DASTClaim added in v0.1.8

type DASTClaim struct {
	CWE             string `json:"cwe"`
	Location        string `json:"location"`
	Rule            string `json:"rule"`
	Source          string `json:"source"`
	Fingerprint     string `json:"fingerprint"`
	ProofEvidenceID string `json:"proof_evidence_id"`
}

DASTClaim is the typed result of a dynamic check. Source and Fingerprint are stable tokens supplied by the first-party check corpus and identify the exact runtime observation without carrying response content or credentials.

func (DASTClaim) Capability added in v0.1.8

func (DASTClaim) Capability() Capability

Capability identifies this claim's brain.

func (DASTClaim) Validate added in v0.1.8

func (c DASTClaim) Validate() error

Validate requires structured finding fields and stable, secret-free dedup tokens.

type Judgment

type Judgment struct {
	ID            shared.ID
	EngagementID  shared.ID
	Capability    Capability
	SubjectKind   SubjectKind
	SubjectID     shared.ID
	Claim         Claim
	State         State
	EvidenceScore int
	ProposedBy    string `json:"proposed_by"`
	// VerifiedBy and VerdictRationale are sealed-verdict provenance. They are set
	// only by ApplyVerdict for a distinct verifier; proposed and accepted
	// judgments leave both empty.
	VerifiedBy       string `json:"verified_by"`
	VerdictRationale string `json:"verdict_rationale"`
	Version          int
	Audit            shared.Audit
}

Judgment is one propose→verify→confirm unit of AI analysis. It is a CLAIM until a DISTINCT verifier seals a verdict (gated capabilities) or a human accepts it (ungated). Tenant-scoped via EngagementID (R9). ProposedBy is attribution only – it confers no power to move the score.

func New

func New(id, engagementID shared.ID, capability Capability, subjectKind SubjectKind, subjectID shared.ID, claim Claim, proposer string, now time.Time) (Judgment, error)

New builds a PROPOSED judgment at EvidenceScore 0 (the proposer can never set a score). It validates the closed vocabularies + the typed claim; proposer is recorded for attribution only.

func (Judgment) Accept

func (j Judgment) Accept(by string, now time.Time) (Judgment, error)

Accept confirms an UNGATED judgment by human acceptance (there is nothing to refute at 75). It refuses a gated capability (use ApplyVerdict) and a self-accepting proposer.

func (Judgment) ApplyVerdict

func (j Judgment) ApplyVerdict(v verdict.Verdict, now time.Time) (Judgment, error)

ApplyVerdict moves a GATED judgment's score via a DISTINCT verifier's verdict – the only path that scores a gated capability. It refuses an ungated capability (use Accept), an invalid verdict, and a self-confirming verifier. >= EvidenceThreshold ⇒ confirmed, else refuted. Pure state change; the use case MUST have sealed the verdict as evidence first (R10).

func (Judgment) MeetsEvidenceBar

func (j Judgment) MeetsEvidenceBar() bool

MeetsEvidenceBar reports whether the judgment cleared the shared threshold.

func (Judgment) Publishable

func (j Judgment) Publishable() bool

Publishable reports whether a judgment may surface in a customer-facing deliverable (R2): it must be confirmed, and for a GATED capability also clear the evidence bar. Ungated capabilities are publishable once confirmed (human-accepted). Mirrors finding.Publishable.

type PromotionChange added in v0.1.8

type PromotionChange string

PromotionChange is the closed set of finding-priority effects a cross-pillar rule may propose.

const (
	PromotionEscalate      PromotionChange = "escalate"
	PromotionDeescalate    PromotionChange = "de_escalate"
	PromotionFlagForReview PromotionChange = "flag_for_review"
)

func ExpectedEffect added in v0.1.8

func ExpectedEffect(rule string) (PromotionChange, bool)

ExpectedEffect returns the PromotionChange that the given rule is allowed to produce. Unknown rules are rejected so claims cannot introduce new promotion behavior.

func (PromotionChange) Valid added in v0.1.8

func (c PromotionChange) Valid() bool

type PromotionClaim added in v0.1.8

type PromotionClaim struct {
	FindingID      shared.ID        `json:"finding_id"`
	Rule           string           `json:"rule"`
	Inputs         []PromotionInput `json:"inputs"`
	Proposed       PromotionChange  `json:"proposed"`
	Uncertainty    []string         `json:"uncertainty,omitempty"`
	Fingerprint    string           `json:"fingerprint"`
	FindingVersion int              `json:"finding_version"`
	BeforePriority int              `json:"before_priority"`
	AfterPriority  int              `json:"after_priority"`
}

PromotionClaim proposes a deterministic priority change. It is inert until a distinct verifier's sealed verdict clears the evidence bar. Uncertain inputs may only produce a review flag.

func (PromotionClaim) Capability added in v0.1.8

func (PromotionClaim) Capability() Capability

func (PromotionClaim) Validate added in v0.1.8

func (c PromotionClaim) Validate() error

type PromotionInput added in v0.1.8

type PromotionInput struct {
	Kind       PromotionInputKind `json:"kind"`
	ID         shared.ID          `json:"id"`
	EvidenceID shared.ID          `json:"evidence_id,omitempty"`
}

PromotionInput links a promotion to the exact record and, where available, its sealed evidence.

type PromotionInputKind added in v0.1.8

type PromotionInputKind string

PromotionInputKind identifies a typed record that supports or contradicts a promotion.

const (
	PromotionInputReachability PromotionInputKind = "reachability_judgment"
	PromotionInputAttackPath   PromotionInputKind = "attack_path"
	PromotionInputDetection    PromotionInputKind = "detection"
	PromotionInputPrior        PromotionInputKind = "prior_promotion"
)

func (PromotionInputKind) Valid added in v0.1.8

func (k PromotionInputKind) Valid() bool

type ReachabilityClaim

type ReachabilityClaim struct {
	Reachable  ReachabilityState `json:"reachable"`
	Tier       ReachabilityTier  `json:"tier"`
	Path       []string          `json:"path,omitempty"`
	Confidence int               `json:"confidence"`
}

ReachabilityClaim is the typed result of a reachability judgment: whether the vulnerable symbol is reachable, by which tier, and along what call path. Confidence is 0..100.

func (ReachabilityClaim) Capability

func (ReachabilityClaim) Capability() Capability

Capability identifies this claim's brain.

func (ReachabilityClaim) Supersedes

func (c ReachabilityClaim) Supersedes(prior ReachabilityClaim) bool

Supersedes reports whether this claim should override prior – true only when this claim was produced by a STRICTLY STRONGER tier of proof (a deterministic Tier-2 call-graph result overrides an LLM Tier-1.5 claim, whether they agree or contradict). Same-or-lower tier does NOT supersede: a re-run at equal strength leaves the stored verdict standing (no churn), and a weaker re-analysis never downgrades a stronger proof. An unknown/invalid tier (Rank 0) can neither supersede nor be preserved against any valid tier.

func (ReachabilityClaim) Validate

func (c ReachabilityClaim) Validate() error

Validate enforces the closed verdict + tier vocabularies and a 0..100 confidence.

type ReachabilityState

type ReachabilityState string

ReachabilityState is the closed verdict vocabulary of a reachability judgment. The wire values are stable (persisted in the claim JSONB + consumed by OpenVEX justification mapping).

const (
	Reachable    ReachabilityState = "reachable"
	NotReachable ReachabilityState = "not_reachable"
	ReachUnknown ReachabilityState = "unknown"
)

func (ReachabilityState) Valid

func (s ReachabilityState) Valid() bool

Valid reports whether s is a known reachability verdict (fail-closed: anything else is rejected).

type ReachabilityTier

type ReachabilityTier string

ReachabilityTier is the analysis tier that produced a verdict, ordered by strength of proof tier-0 = dependency-graph presence · tier-1 = direct import · tier-1.5 = bounded source call-path · tier-2 = call-graph proof. A higher-ranked tier OVERRIDES a lower one.

const (
	Tier0   ReachabilityTier = "tier-0"
	Tier1   ReachabilityTier = "tier-1"
	Tier1_5 ReachabilityTier = "tier-1.5"
	Tier2   ReachabilityTier = "tier-2"
)

func (ReachabilityTier) Rank

func (t ReachabilityTier) Rank() int

Rank orders tiers by strength of proof (higher = stronger); 0 ⇒ unknown/invalid. Compare ranks to decide whether a new verdict supersedes a stored one (a Tier-2 proof overrides a Tier-1.5 claim).

func (ReachabilityTier) Valid

func (t ReachabilityTier) Valid() bool

Valid reports whether t is a known tier (fail-closed).

type RiskNarrativeClaim

type RiskNarrativeClaim struct {
	Drivers  []string `json:"drivers"`  // e.g. "kev", "epss>0.5", "cvss>=9", "reachable"
	Priority int      `json:"priority"` // 1..5 (mirrors the Go-computed priority)
}

RiskNarrativeClaim explains the Go-computed priority via STRUCTURED drivers (never prose): the renderer composes the sentence from these fields. It is NOT evidence-gated – there is nothing to "refute at 75"; a human accepts it.

func (RiskNarrativeClaim) Capability

func (RiskNarrativeClaim) Capability() Capability

Capability identifies this claim's brain.

func (RiskNarrativeClaim) Validate

func (c RiskNarrativeClaim) Validate() error

Validate requires at least one driver and a 1..5 priority.

type SASTClaim

type SASTClaim struct {
	CWE      string    `json:"cwe"`
	Location string    `json:"location"` // path[:line]
	Rule     string    `json:"rule"`
	AssetID  shared.ID `json:"asset_id"`
}

SASTClaim is the typed result of a SAST judgment: the weakness (CWE), where, and the rule that fired. No free-text – a "hardcoded secret at L42" finding renders from these fields.

func (SASTClaim) Capability

func (SASTClaim) Capability() Capability

Capability identifies this claim's brain.

func (SASTClaim) Validate

func (c SASTClaim) Validate() error

Validate requires bounded, structured fields that make a SAST hit renderable + dedupable.

type State

type State string

State is the judgment lifecycle.

const (
	StateProposed  State = "proposed"  // EvidenceScore 0; inert
	StateConfirmed State = "confirmed" // a sealed verdict (gated) or human acceptance (ungated) cleared it
	StateRefuted   State = "refuted"   // a sealed verdict left it below the bar
)

func (State) Valid

func (s State) Valid() bool

Valid reports whether s is a known state.

type StrideCategory

type StrideCategory string

StrideCategory is one STRIDE threat class (closed vocabulary; the renderer composes the human sentence from this + the threatened subject element – never free prose).

const (
	Spoofing             StrideCategory = "spoofing"
	Tampering            StrideCategory = "tampering"
	Repudiation          StrideCategory = "repudiation"
	InfoDisclosure       StrideCategory = "info_disclosure"
	DenialOfService      StrideCategory = "denial_of_service"
	ElevationOfPrivilege StrideCategory = "elevation_of_privilege"
)

func (StrideCategory) Valid

func (s StrideCategory) Valid() bool

Valid reports whether s is a known STRIDE category.

type SubjectKind

type SubjectKind string

SubjectKind is what a judgment is ABOUT (closed vocabulary).

const (
	SubjectFinding       SubjectKind = "finding"
	SubjectComponent     SubjectKind = "component"
	SubjectVulnerability SubjectKind = "vulnerability"
	SubjectEngagement    SubjectKind = "engagement"
	SubjectDataFlow      SubjectKind = "data_flow" // a threat-model data flow (a boundary crossing)
)

func (SubjectKind) Valid

func (k SubjectKind) Valid() bool

Valid reports whether k is a known subject kind.

type ThreatClaim

type ThreatClaim struct {
	Category StrideCategory `json:"category"`
	Asset    string         `json:"asset"` // legacy display text; never used for asset attribution
	AssetID  shared.ID      `json:"asset_id"`
}

ThreatClaim is a proposed STRIDE threat over the architecture model: the STRIDE category, plus the optional Asset.ID at risk (e.g. the classified data an info-disclosure exposes) – both STRUCTURED tokens, never free prose. The threatened model element (a component or data flow) is the Judgment's SUBJECT (SubjectComponent / SubjectDataFlow), not part of the claim. Gated: a human verifier ratifies it ("human-confirmed"); the agent only ever proposes it at score 0.

func (ThreatClaim) Capability

func (ThreatClaim) Capability() Capability

Capability identifies this claim's brain.

func (ThreatClaim) Validate

func (c ThreatClaim) Validate() error

Validate enforces the closed STRIDE vocabulary and bounds the optional asset reference (a token-length id, never prose).

type VexJustificationClaim

type VexJustificationClaim struct {
	Justification vex.OpenVexJustification `json:"justification"`
}

VexJustificationClaim is a proposed OpenVEX justification for why a finding is NOT_AFFECTED – the AI's STRUCTURED choice from the CLOSED OpenVEX justification set, never free prose. The finding it applies to is the Judgment's SUBJECT (SubjectFinding), not part of the claim. Gated: a distinct human verifier ratifies it before the export trusts it (it asserts "not affected" in a published deliverable); the agent only proposes it at score 0. It COMPLEMENTS the deterministic reachability-tier justification.

func (VexJustificationClaim) Capability

func (VexJustificationClaim) Capability() Capability

Capability identifies this claim's brain.

func (VexJustificationClaim) Validate

func (c VexJustificationClaim) Validate() error

Validate enforces the closed OpenVEX justification vocabulary (fail-closed; never a free-text reason).

Jump to

Keyboard shortcuts

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