Documentation
¶
Overview ¶
Package report defines the canonical audit report and the renderers that present it. The JSON report is the single source of truth (it carries its own schema_version, independent of the codefit version); plain-text, TUI and HTML are interchangeable renderers over it, chosen by TTY detection (PRD section 18).
It defines AuditReport and three Renderer implementations — JSON (canonical), plain text, and an HTML placeholder — plus TTY detection so the plain renderer is used in pipes/CI/MCP.
Index ¶
- Constants
- func ClassifyEndpoints(eps []EndpointReport) (actionable []EndpointReport, resolvedClean []ResolvedCleanEndpoint, ...)
- type AuditReport
- type BaselineSummary
- type CertaintyLevel
- type Concern
- type EndpointReport
- type FrontierEndpoint
- type JSONRenderer
- type RegressionItem
- type RegressionRisk
- type Renderer
- type ResolvedCleanEndpoint
Constants ¶
const SchemaVersion = "1.0"
SchemaVersion is the version of the canonical JSON report format, independent of the codefit binary version so report consumers can migrate in a controlled way (PRD §18).
Variables ¶
This section is empty.
Functions ¶
func ClassifyEndpoints ¶
func ClassifyEndpoints(eps []EndpointReport) (actionable []EndpointReport, resolvedClean []ResolvedCleanEndpoint, frontier []FrontierEndpoint)
ClassifyEndpoints splits aggregated endpoints into three buckets, one per resolution level — all by facts codefit already computes, no new judgment:
- actionable — resolved locally AND has a gap (CertainConcerns>0, Actionable>0): full detail, the agent acts on these.
- resolved_clean — resolved locally, NO gap (CertainConcerns>0, Actionable==0): named + a verification fact; codefit checked and it is clean.
- frontier — not resolved locally (CertainConcerns==0): named; the data left the body, the agent follows it in the code.
The order matters: CertainConcerns==0 → frontier first, so a frontier-only endpoint that happens to carry an access-gap signal is still named as frontier (codefit did not resolve it locally), never promoted to actionable. Actionable endpoints are returned WHOLE (all their concerns, including any frontier concern of the same endpoint, because the agent reasons the endpoint). Input order (hardest gap first) is preserved within each bucket.
Types ¶
type AuditReport ¶
type AuditReport struct {
SchemaVersion string `json:"schema_version"`
CodefitVersion string `json:"codefit_version"`
Timestamp time.Time `json:"timestamp"`
Project string `json:"project"`
Language string `json:"language"`
Commit string `json:"commit,omitempty"`
Score scoring.ScoreSummary `json:"score"`
Blocked bool `json:"blocked"`
BlockReason string `json:"block_reason,omitempty"`
Baseline *BaselineSummary `json:"baseline,omitempty"`
Findings []findings.Finding `json:"findings"`
// Surface is the auditable structural surface the agent must reason about
// (PRD section 10), aggregated across sensors.
Surface []findings.SurfaceItem `json:"surface,omitempty"`
// Endpoints is the synthesis view (codefit-scan-all): the deterministic
// findings and the surface grouped by the handler they belong to, each
// endpoint's concerns ordered by certainty (deterministic → confirmed →
// frontier). It is the complete picture per endpoint for the agent to reason;
// the flat Findings/Surface remain for traceability.
Endpoints []EndpointReport `json:"endpoints,omitempty"`
// CoverageNote states which classes of problems were not audited (derived
// from the coverage manifest), so the report always informs its own limits
// (PRD section 21). Populated once the coverage manifest exists (Fase C).
CoverageNote string `json:"coverage_note,omitempty"`
RegressionRisk *RegressionRisk `json:"regression_risk,omitempty"`
SensorResults []findings.SensorResult `json:"sensor_results"`
}
AuditReport is the canonical, language-agnostic audit result. JSON is the single source of truth; every renderer derives from this struct.
type BaselineSummary ¶
type BaselineSummary struct {
Active bool `json:"active"`
NewFindings int `json:"new_findings"`
BaselinedFindings int `json:"baselined_findings"`
}
BaselineSummary reports how many findings were new vs. recorded as historical debt when a baseline is active (RF-10).
type CertaintyLevel ¶
type CertaintyLevel string
CertaintyLevel ranks how certain codefit is about a concern — the report's epistemological honesty. A deterministic finding is an ASSERTION (codefit saw a conclusive pattern, confidence 1.0). A surface concern is a QUESTION codefit hands to the agent: structurally confirmed (it saw the shape locally) or at the frontier (the data left the handler body, codefit could not see). The agent must distinguish what codefit affirms from what it asks; it never flattens them.
const ( Deterministic CertaintyLevel = "deterministic" // codefit affirms (rule, 1.0) SurfaceConfirmed CertaintyLevel = "surface_confirmed" // codefit asks; saw the shape locally SurfaceFrontier CertaintyLevel = "surface_frontier" // codefit asks; the data left the body )
type Concern ¶
type Concern struct {
Certainty CertaintyLevel `json:"certainty"`
Affirms bool `json:"affirms"` // true: codefit asserts a fact; false: codefit asks the agent
Source string `json:"source"` // "rule" | "surface"
ID string `json:"id"`
Category string `json:"category"` // security | idor | authz | overfetch
Title string `json:"title"`
Description string `json:"description,omitempty"` // deterministic finding description
Signals []string `json:"signals,omitempty"` // surface structural_signals (facts)
Question string `json:"question,omitempty"` // surface reason_to_review
Line int `json:"line"`
Confidence float64 `json:"confidence"`
Probabilistic bool `json:"probabilistic"`
// RefinesAuthz marks an IDOR concern whose endpoint also has an authz concern:
// IDOR is the structural refinement of authz (the sensitive handler also
// receives a client id). A fact about structure, not a judgment.
RefinesAuthz bool `json:"refines_authz,omitempty"`
// Actionable is true when the concern is a missing/broken control codefit
// detected (an affirmed finding, no authz/ownership check, or no field limit).
Actionable bool `json:"actionable"`
// Gap names the KIND of missing control, hardest first: "affirmed" (a
// deterministic finding), "access" (no authz/ownership on a sensitive
// handler), "exposure" (a serialization with no select/omit). Empty when the
// concern is not an actionable gap (e.g. a checked handler, or the frontier).
Gap string `json:"gap,omitempty"`
}
Concern is one thing to review about an endpoint, from either source — a deterministic rule finding or a mapped surface item. Affirms records whether codefit asserts it (deterministic) or asks it (surface), so the distinction is never ambiguous.
type EndpointReport ¶
type EndpointReport struct {
File string `json:"file"`
Line int `json:"line"` // handler anchor line (0 = module scope)
Method string `json:"method,omitempty"` // GET/POST/... when known
Actionable int `json:"actionable"` // count of missing/broken-control concerns
CertainConcerns int `json:"certain_concerns"` // deterministic + surface_confirmed
Concerns []Concern `json:"concerns"`
}
EndpointReport is the complete picture of one handler: all its concerns from both sources, ordered by certainty (deterministic → confirmed → frontier).
func AggregateEndpoints ¶
func AggregateEndpoints(fs []findings.Finding, surface []findings.SurfaceItem) []EndpointReport
AggregateEndpoints groups deterministic findings and surface items by the handler they belong to and assembles the per-endpoint picture: concerns ordered by certainty within an endpoint (deterministic → confirmed → frontier), and endpoints ordered by their ACTIONABLE structural gaps, hardest kind first (affirmed deterministic → missing access control → over-exposure), then by certain-concern count. This surfaces the real findings, not the most instrumented endpoints. Ordering is by FACT (which control is missing), never by severity — the agent judges danger. It invents nothing: every concern comes from a real finding or surface item with its id.
type FrontierEndpoint ¶
type FrontierEndpoint struct {
File string `json:"file"`
Line int `json:"line,omitempty"`
Method string `json:"method,omitempty"`
Categories []string `json:"categories"`
}
FrontierEndpoint names a frontier-only endpoint — every one of its concerns is surface_frontier (the data left the handler body, local_access_detected=false), so codefit concluded nothing locally about it. It is NAMED, not detailed: the agent goes to the code to follow the data regardless, so the concern detail would not save it the trip (ADR 0008). It carries the file and the categories at stake, one line, for the agent to know what is pending and request the full detail on demand via codefit-scan-endpoint.
type JSONRenderer ¶
type JSONRenderer struct{}
JSONRenderer writes the canonical JSON, indented. In the MCP-first model the report is delivered as JSON to the agent; this is the only renderer in v1 (an HTML renderer is a future addition over the same canonical report).
func (JSONRenderer) Render ¶
func (JSONRenderer) Render(w io.Writer, r AuditReport) error
type RegressionItem ¶
type RegressionItem struct {
Symbol string `json:"symbol"`
File string `json:"file"`
Callsites []string `json:"callsites,omitempty"`
Reason string `json:"reason,omitempty"`
}
RegressionItem is a single function/symbol at risk from recent changes.
type RegressionRisk ¶
type RegressionRisk struct {
High []RegressionItem `json:"high,omitempty"`
Medium []RegressionItem `json:"medium,omitempty"`
}
RegressionRisk groups regression-risk items by level (RF-06, --since mode).
type Renderer ¶
type Renderer interface {
Render(w io.Writer, r AuditReport) error
}
Renderer writes an AuditReport to w. Renderers never reach into the core; they only consume the canonical report.
type ResolvedCleanEndpoint ¶
type ResolvedCleanEndpoint struct {
File string `json:"file"`
Line int `json:"line,omitempty"`
Method string `json:"method,omitempty"`
Verification string `json:"verification"`
}
ResolvedCleanEndpoint names an endpoint codefit resolved LOCALLY and found clean: it accessed data locally (CertainConcerns>0) and codefit verified the controls are present — no gap. It is NAMED (file, method) plus one VERIFICATION FACT that affirms what codefit checked ("an authorization check is present; field selection is present — no gap found"). This is the crux of the three- bucket split: resolved_clean is an AFFIRMATION (codefit looked and it is clean), epistemologically OPPOSITE to a frontier endpoint (codefit could NOT conclude). Flattening the two into a single "not detailed" bucket would be the same error as the old frontier wording — so they are kept distinct on purpose.