report

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jun 28, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

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

View Source
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"`
	// Fingerprint is the concern's baseline content identity (findings.Fingerprint).
	// The agent passes it to codefit-baseline-accept / -prune.
	Fingerprint string `json:"fingerprint,omitempty"`
	// Baseline is the concern's delta vs the previous baseline, set by the scan-all
	// handler: "new" | "changed" | "known" | "acknowledged" (empty when no baseline).
	Baseline string `json:"baseline,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.

Jump to

Keyboard shortcuts

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