Documentation
¶
Overview ¶
Package promotion implements the use-case layer for deterministic finding-priority promotion. It contains two narrow authorities:
Evaluator: loads findings, attack-path graph, detections, and reachability judgments, builds promotion.Snapshot values, calls the pure promotion.Evaluate function, and proposes typed judgment.PromotionClaim judgments. Its local reader interfaces expose no finding, judgment, or promotion mutation.
ConfirmedRecorder: receives an already publishable confirmed judgment.Judgment with CapPromotion, seals a finding-linked evidence payload, and atomically applies the promotion through ports.PromotionStore.
Neither authority imports model/pillar/MCP code. Inputs are sourced, sorted, and tenant-bound; the caller never provides a tenant ID.
Index ¶
Constants ¶
const PromotionEvidenceKind = "promotion_application"
PromotionEvidenceKind is the evidence-chain kind for sealed promotion applications.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ConfirmedRecorder ¶
type ConfirmedRecorder struct {
// contains filtered or unexported fields
}
ConfirmedRecorder receives an already publishable confirmed judgment.Judgment with CapPromotion, loads the finding for CAS fields, validates subject/engagement consistency, seals a finding-linked evidence payload (crash-recoverable), and atomically applies the promotion through ports.PromotionStore. It cannot propose or verify.
func NewConfirmedRecorder ¶
func NewConfirmedRecorder( evidence evidenceSealer, promotions confirmedPromotionStore, findings confirmedFindingReader, engagement engagementReader, audit confirmedAuditRecorder, clock ports.Clock, ) (*ConfirmedRecorder, error)
NewConfirmedRecorder validates dependencies and returns a ConfirmedRecorder.
func (*ConfirmedRecorder) RecordConfirmed ¶
RecordConfirmed applies a confirmed promotion judgment. The judgment must:
- be CapPromotion
- be Publishable (confirmed + meets evidence bar)
- have evidence score >= verdict.EvidenceThreshold
- have SubjectKind == SubjectFinding and SubjectID == claim.FindingID
- belong to the same engagement as the finding
- contain a valid PromotionClaim
On success the method loads the finding for CAS fields, seals a finding-linked evidence payload (crash-recoverable via LookupSealedForFinding), then atomically applies the promotion through the store. For flag_for_review effects, lifecycle evidence is recorded without priority/version mutation. Retries with the same judgment + fingerprint are idempotent.
Audit reliability: the mutation and audit are ordered so that we never return success without a required audit. If audit fails AFTER the store mutation succeeded, we return the audit error (lifecycle/evidence are canonical and the caller can retry the audit). Deterministic event and evidence IDs ensure retry is recoverable.
type Evaluator ¶
type Evaluator struct {
// contains filtered or unexported fields
}
Evaluator loads deterministic inputs and proposes promotion claims. It holds no finding, judgment, or promotion mutation authority.
func NewEvaluator ¶
func NewEvaluator( p proposer, findings findingReader, judgments judgmentReader, bindings attackPathReader, assets assetReader, detections detectionReader, engagement engagementReader, promotions promotionEventReader, clock clock, audit proposalAuditRecorder, ) (*Evaluator, error)
NewEvaluator validates dependencies and returns an Evaluator.
func (*Evaluator) Evaluate ¶
Evaluate loads all promotion-relevant signals for the engagement, evaluates the deterministic promotion rules for every finding, and proposes new judgment.PromotionClaim judgments through the narrow proposer. It requires tenant context and validates engagement ownership through the chokepoint.
Stable ordering: findings are sorted by ID; duplicate fingerprints are skipped; existing proposals with unchanged fingerprints are not re-proposed. Evaluate never verifies or mutates a finding.
type Reconciler ¶
type Reconciler struct {
// contains filtered or unexported fields
}
Reconciler is the distinct recovery authority for confirmed promotions. It applies already-confirmed judgments and retries only outstanding audits; it has no proposal or verdict authority.
func NewReconciler ¶
func NewReconciler(judgments judgmentReader, audits ports.PromotionAuditTracker, recorder ports.ConfirmedPromotionRecorder, audit ports.IdempotentAuditLogger, clock ports.Clock) (*Reconciler, error)
NewReconciler creates the durable promotion recovery authority.
type ReconciliationRunner ¶
type ReconciliationRunner struct {
// contains filtered or unexported fields
}
ReconciliationRunner invokes a reconciler for every discovered tenant-bound engagement.
func NewReconciliationRunner ¶
func NewReconciliationRunner(scopes ports.PromotionReconciliationScopeReader, evaluator ports.PromotionEvaluator, reconciler ports.PromotionReconciler, log *slog.Logger) (*ReconciliationRunner, error)
func (*ReconciliationRunner) RunOnce ¶
func (r *ReconciliationRunner) RunOnce(ctx context.Context) error
RunOnce reconciles every scope. Per-scope failures are logged and do not block other tenants; scope discovery and cancellation failures are returned.
func (*ReconciliationRunner) RunPeriodic ¶
func (r *ReconciliationRunner) RunPeriodic(ctx context.Context, interval time.Duration)
RunPeriodic reconciles at interval until ctx is cancelled.
func (*ReconciliationRunner) SetGovernanceReconciler ¶
func (r *ReconciliationRunner) SetGovernanceReconciler(governance ports.GovernanceReconciler)
SetGovernanceReconciler adds server-only durable governance recovery without granting the evaluator or any read path mutation authority.