Documentation
¶
Overview ¶
Package leverage is the neutral home for the cross-SSP leveraged-authorization projection and aggregation. It was extracted from internal/api/handler/oscal so that internal/api/handler (which oscal imports, not the other way round) can read the same leverage data without an import cycle — the compliance-progress endpoint (package oscal) and the lineage engine (package handler) both build on it.
It may import relational, relational/risks and converters/labelfilter; it must NOT import anything under internal/api.
Index ¶
- func AggregateByControl(summaries []LinkSummary) map[ControlKey]ControlAggregate
- func BulkResolveUpstreamResponsibilities(db *gorm.DB, providedUUIDs []uuid.UUID) (map[uuid.UUID][]Responsibility, error)
- func DriftDedupeKey(linkID uuid.UUID) string
- func NormalizeControlID(controlID string) string
- func ProjectForControl(db *gorm.DB, controlID string) (map[uuid.UUID][]Projection, error)
- func ResponsibilityPosture(db *gorm.DB, downstreamSSPID uuid.UUID, responsibilityUUIDs []uuid.UUID) (map[uuid.UUID]string, error)
- type ControlAggregate
- type ControlKey
- type LinkSummary
- type Origin
- type Projection
- type Responsibility
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AggregateByControl ¶
func AggregateByControl(summaries []LinkSummary) map[ControlKey]ControlAggregate
AggregateByControl folds link summaries into per-control aggregates. Pure and unit-testable: statement-scoped and control-scoped links for the same control-id collapse into one ControlKey, statuses take the worst, satisfaction is full only if all links are full, counts sum, origins dedupe by (upstream SSP, offering), and Credit holds only when every link is active and full.
func BulkResolveUpstreamResponsibilities ¶
func BulkResolveUpstreamResponsibilities(db *gorm.DB, providedUUIDs []uuid.UUID) (map[uuid.UUID][]Responsibility, error)
BulkResolveUpstreamResponsibilities is the batched resolver: two queries total regardless of how many providedUUIDs are requested, rather than two queries per item (the catalog list and the leveraged-controls projection each resolve responsibilities for many items/links in one request). The two-step lookup is unavoidable because ControlImplementationResponsibility and ProvidedControlImplementation are siblings under Export with no direct FK between them — only the shared OSCAL-level provided-uuid value — so responsibilities are scoped by (export_id, provided_uuid) pairs, not provided_uuid alone, since provided-uuid values are only unique within a single upstream's Export. providedUUIDs with no matching ProvidedControlImplementation row (e.g. the upstream row was since deleted) map to an empty slice, not an error or a missing key.
func DriftDedupeKey ¶
DriftDedupeKey returns the dedupe key for the drift risk associated with a single SSPLeverageLink. One risk per leverage link: the link itself is the natural, deterministic scope (no risk template is involved, unlike evidence-driven risks), and the key is directly parseable back to the link that produced it without needing a separate link table. The "leverage-drift:%s" format keeps the drift writer (applyDriftToLink) and the projection reader in lockstep.
func NormalizeControlID ¶
NormalizeControlID folds a control-id to the canonical key form (trimmed, upper).
func ProjectForControl ¶
ProjectForControl builds the Projection for every downstream SSP holding at least one leverage link for controlID (UPPER-folded match, no catalog id — the same keying every leverage read uses). It groups the links by downstream SSP and runs the same batched resolution projectLinks performs per SSP, so ResponsibilityPosture and the drift-risk lookup (both SSP-scoped) run once per involved downstream SSP — bounded by subscriber count, acceptable because this backs the drawer endpoint only. The returned map is keyed by downstream SSP id.
func ResponsibilityPosture ¶
func ResponsibilityPosture(db *gorm.DB, downstreamSSPID uuid.UUID, responsibilityUUIDs []uuid.UUID) (map[uuid.UUID]string, error)
ResponsibilityPosture computes per-responsibility compliance posture (satisfied / not-satisfied / unknown) for a downstream SSP, using the same evidence status-count/collapse logic as control-keyed posture (relational.CollapseEvidenceStatus), but keyed by responsibility_uuid via filter_responsibilities instead of by (catalogId, controlId) via filter_controls (BCH-1339). Feeds the Inherited Capability projection so a downstream can see whether an inherited responsibility is actually backed by satisfying evidence, not just recorded as satisfied at subscribe time. Every requested uuid is always present in the returned map — defaulting to "unknown" when no filter targets it — never an absent key, matching BulkResolveUpstreamResponsibilities's convention.
Types ¶
type ControlAggregate ¶
type ControlAggregate struct {
Links int
// Credit is the inherited-credit rule at the leverage layer: ≥1 link AND every link
// Status == active AND every link (live-derived) Satisfaction == full AND
// TotalResponsibilities > 0. The last clause denies credit to a link whose upstream
// responsibilities resolve to empty — a dangling link (upstream Provided/responsibility
// rows deleted, so BulkResolve returns []) or a genuinely zero-responsibility offering
// — which would otherwise silently inflate compliance before drift detection runs.
// The evidence-wins and in-scope conditions are applied by the consumer, not here.
Credit bool
// Status is the worst link status: drifted > revoked > superseded > active.
Status relational.SSPLeverageStatus
// Satisfaction is full iff every link is full, else partial.
Satisfaction relational.SSPLeverageSatisfaction
// OutstandingCount and TotalResponsibilities are summed across links.
OutstandingCount int
TotalResponsibilities int
// InheritedFrom is the deduped set of upstream origins, in first-seen order.
InheritedFrom []Origin
}
ControlAggregate is the per-control rollup of every leverage link sharing a ControlKey — the unit the compliance and lineage surfaces read.
type ControlKey ¶
ControlKey identifies a (downstream SSP, control-id) pair. ControlID must be UPPER-folded and trimmed via NormalizeControlID before use as a key — leverage links are matched by control-id alone (no catalog id), the established precedent shared with implStatusBySSP and implemented requirements.
type LinkSummary ¶
type LinkSummary struct {
LinkID uuid.UUID
DownstreamSSPID uuid.UUID
UpstreamSSPID uuid.UUID
OfferingID uuid.UUID
UpstreamSSPTitle string
OfferingTitle string
OfferingVersion int
ControlID string // as stored (casing preserved); folded only when aggregating
StatementID *string
Status relational.SSPLeverageStatus
Satisfaction relational.SSPLeverageSatisfaction
OutstandingCount int
TotalResponsibilities int
}
LinkSummary is one leverage link reduced to what the cross-SSP compliance and lineage read surfaces need: the identity of the link, the upstream it came from (with resolved titles), its lifecycle Status, and its LIVE-derived Satisfaction and responsibility counts. Satisfaction is recomputed from the current satisfied rows via DeriveSatisfaction — never the link's stored satisfaction column, which can rot when the upstream changes its responsibility set.
func Summarize ¶
Summarize builds a LinkSummary for every leverage link, live-deriving satisfaction, in ~7 bulk queries regardless of link count. sspID nil summarizes every downstream SSP (lineage global scope); non-nil restricts to that one downstream SSP.
It is deliberately lighter than Project: no per-responsibility posture and no drift risk id (those back the drawer/detail views, not the counts), so it stays cheap enough to run on every lineage engine build.
type Origin ¶
type Origin struct {
UpstreamSSPID uuid.UUID
UpstreamSSPTitle string
OfferingID uuid.UUID
OfferingTitle string
OfferingVersion int
}
Origin is one upstream capability an inherited control draws from, deduped by (UpstreamSSPID, OfferingID) within a ControlAggregate.
type Projection ¶
type Projection struct {
Link relational.SSPLeverageLink
OfferingTitle string
ByComponentID uuid.UUID
// Inherited is the downstream's own InheritedControlImplementation row this link
// created; nil only if it has since been deleted out from under the link.
Inherited *relational.InheritedControlImplementation
Satisfaction relational.SSPLeverageSatisfaction
Outstanding []Responsibility
// Responsibilities is the FULL upstream responsibility set under this link (uuid +
// description), so downstream surfaces can label every responsibility — including
// ones already satisfied — with the upstream's own text. Outstanding is the subset
// of this with no matching downstream satisfied entry.
Responsibilities []Responsibility
Posture map[uuid.UUID]string
DriftRiskID *uuid.UUID
}
Projection is one downstream leverage link with everything the read models need already resolved: the live-recomputed satisfaction (never the link's cached value), the outstanding responsibilities, the evidence-backed posture, the open drift risk, the offering title, and the by-component + inherited row the link hangs off.
Both the /leveraged-controls endpoint and the shared-responsibility rollup read this, so satisfaction is derived in exactly one place and neither surface can drift from the other. oscal aliases leveragedControlProjection to it.
func Project ¶
Project builds the Projection for every leverage link on one downstream SSP in six queries at THIS level, independent of link count — the batching that replaced this code's original four-queries-per-link loop, preserved here so no caller can regress it into an N+1. In particular the ResponsibilityPosture(db, sspID, allResponsibilityUUIDs) call below must stay a single call for every uuid, never one per link.
The end-to-end cost is ~6 + N, not six: ResponsibilityPosture finishes with a per-responsibility loop (relational.EvidenceStatusCountsForFilters) that issues one evidence aggregate — count(DISTINCT uuid) grouped by status->>state, over the latest-evidence-stream subquery and the label-filter joins — for every responsibility carrying at least one FilterResponsibility link. Those N queries are the expensive ones, and both /leveraged-controls and GET /:id/shared-responsibility pay them. Hoisting that loop rewrites evidence aggregation and belongs in its own change.
type Responsibility ¶
type Responsibility struct {
ResponsibilityUUID uuid.UUID `json:"responsibilityUuid"`
Description string `json:"description"`
}
Responsibility is the minimal upstream-responsibility shape both the catalog exposure and the subscribe/projection paths need: enough to let a downstream subscriber pick specific responsibility UUIDs to satisfy, and to compute full/partial coverage. Its JSON tags are the wire contract (responsibilityUuid, description); oscal aliases upstreamResponsibility to it so those surfaces are unchanged.
func DeriveSatisfaction ¶
func DeriveSatisfaction(full []Responsibility, satisfiedUUIDs map[uuid.UUID]bool) (relational.SSPLeverageSatisfaction, []Responsibility)
DeriveSatisfaction is the single definition of "full iff every upstream responsibility has a matching downstream satisfied" (vacuously full when full is empty), shared by Subscribe (computing the satisfaction to store on a new leverage link) and every read path (recomputing it live rather than trusting the stored value). Returns the subset of full not covered by satisfiedUUIDs as outstanding.