Documentation
¶
Overview ¶
Package analysis runs the evidence-gated lifecycle for AI "judgments" – the generalized twin of the exploitation gate. A judgment is PROPOSED at EvidenceScore 0; a DISTINCT verifier's verdict (gated capabilities) or a human's acceptance (ungated) is the only thing that confirms it, and the verdict is SEALED into the hash-chained evidence ledger BEFORE the score moves (fail-closed). Verify/Accept are NOT agent-callable: this package is on the agent tool catalog's forbidden-import list (agenttools/arch_test.go), so the proposing agent has no path to confirm its own judgment.
Index ¶
- Constants
- type GovernanceReconciler
- type Service
- func (s *Service) Accept(ctx context.Context, by string, engagementID, judgmentID shared.ID, ...) (judgment.Judgment, error)
- func (s *Service) List(ctx context.Context, engagementID shared.ID) ([]judgment.Judgment, error)
- func (s *Service) Propose(ctx context.Context, proposer string, engagementID shared.ID, ...) (judgment.Judgment, error)
- func (s *Service) SetDASTRecorder(r ports.ConfirmedDASTRecorder)
- func (s *Service) SetPromotionRecorder(r ports.ConfirmedPromotionRecorder)
- func (s *Service) SetSASTRecorder(r ports.ConfirmedSASTRecorder)
- func (s *Service) SetThreatRecorder(r ports.ConfirmedThreatRecorder)
- func (s *Service) Verify(ctx context.Context, verifier string, engagementID, judgmentID shared.ID, ...) (judgment.Judgment, error)
- func (s *Service) VerifyRuntime(ctx context.Context, verifier string, engagementID, judgmentID shared.ID, ...) (judgment.Judgment, error)
- type Store
Constants ¶
const ( ProposedEvidenceKind = "judgment_proposed" VerdictEvidenceKind = "judgment_verdict" AcceptedEvidenceKind = "judgment_accepted" )
Evidence kinds sealed across a judgment's lifecycle.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type GovernanceReconciler ¶ added in v0.1.8
type GovernanceReconciler struct {
// contains filtered or unexported fields
}
GovernanceReconciler retries immutable judgment audit outboxes. It has no transition authority; it can only deliver already-committed payloads.
func NewGovernanceReconciler ¶ added in v0.1.8
func NewGovernanceReconciler(store ports.JudgmentAuditStore, audit ports.IdempotentAuditLogger) (*GovernanceReconciler, error)
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service runs the propose→verify/accept→publishable lifecycle for judgments.
func NewService ¶
func NewService(store Store, ev evidenceSealer, audit ports.IdempotentAuditLogger, clock ports.Clock, ids ports.IDGenerator) (*Service, error)
NewService validates dependencies (all required; the sealer is mandatory because a verdict that cannot be sealed must never move a score).
func (*Service) Accept ¶
func (s *Service) Accept(ctx context.Context, by string, engagementID, judgmentID shared.ID, expectedVersion int) (judgment.Judgment, error)
Accept confirms an UNGATED judgment by human acceptance (no score; there is nothing to refute at 75). It seals the acceptance FIRST, then transitions state under optimistic concurrency. The acceptor must be a non-proposer human (enforced in the domain).
func (*Service) List ¶
List returns the engagement's judgments – the read path for the HTTP layer. Tenant isolation is enforced at the route (withEngTenant resolves the engagement in the caller's tenant) before this is called; the store scopes by engagement.
func (*Service) Propose ¶
func (s *Service) Propose(ctx context.Context, proposer string, engagementID shared.ID, capability judgment.Capability, subjectKind judgment.SubjectKind, subjectID shared.ID, claim judgment.Claim) (judgment.Judgment, error)
Propose records a PROPOSED judgment at EvidenceScore 0, sealing the inert (typed) claim into the evidence chain under the proposer (attribution only; confers no power to score). The agent reaches this only via a propose-only catalog tool (added per-capability with E28/E38).
func (*Service) SetDASTRecorder ¶
func (s *Service) SetDASTRecorder(r ports.ConfirmedDASTRecorder)
SetDASTRecorder wires the optional runtime-confirmed-CapSAST → Kind=dast finding promoter, used only by the VerifyRuntime path. nil ⇒ a runtime confirmation still confirms the judgment but emits no DAST finding. Composition-root only.
func (*Service) SetPromotionRecorder ¶ added in v0.1.8
func (s *Service) SetPromotionRecorder(r ports.ConfirmedPromotionRecorder)
func (*Service) SetSASTRecorder ¶
func (s *Service) SetSASTRecorder(r ports.ConfirmedSASTRecorder)
SetSASTRecorder wires the optional confirmed-CapSAST → finding promoter. nil ⇒ no finding is emitted on confirm. Composition-root only.
func (*Service) SetThreatRecorder ¶
func (s *Service) SetThreatRecorder(r ports.ConfirmedThreatRecorder)
SetThreatRecorder wires the optional confirmed-threat → finding promoter. nil ⇒ no finding is emitted on confirm. Composition-root only.
func (*Service) Verify ¶
func (s *Service) Verify(ctx context.Context, verifier string, engagementID, judgmentID shared.ID, score int, rationale string, expectedVersion int) (judgment.Judgment, error)
Verify applies a DISTINCT verifier's verdict to a GATED judgment. It seals the verdict FIRST (fail-closed), then moves the score+state under optimistic concurrency (expectedVersion). A verdict that loses the race leaves an orphan sealed verdict with no score move – acceptable (the assessment really happened), mirroring the exploitation gate's one-directional provenance.
func (*Service) VerifyRuntime ¶
func (s *Service) VerifyRuntime(ctx context.Context, verifier string, engagementID, judgmentID shared.ID, score int, rationale string, expectedVersion int) (judgment.Judgment, error)
VerifyRuntime is Verify for a verdict produced by a RUNTIME probe (the safe HTTP DAST verifier). It is identical to Verify EXCEPT that a confirmed CapSAST judgment auto-emits a Kind=dast finding (dynamically proven) instead of Kind=sast (statically/LLM confirmed). The runtime-probe path (dastverifier) calls this; the static/LLM path (human review, llmverifier) calls Verify. The distinct verifier, score bar, verdict sealing, and self-confirm guard are all unchanged — only the finding projection differs.
type Store ¶
type Store interface {
ports.JudgmentStore
ports.JudgmentAuditStore
SetScoreState(ctx context.Context, engagementID, id shared.ID, score int, state judgment.State, expectedVersion int) (judgment.Judgment, error)
}
Store is the narrow slice of the judgment repository this use case needs. The score/state MOVER (SetScoreState) lives here (and on the concrete repo) – NOT on a broad ports interface – so a read-only consumer (the agent tool catalog) cannot move a score. Concrete repos satisfy it.