mapping

package
v1.6.0 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 18 Imported by: 2

Documentation

Overview

Package mapping turns the JSON or JSON Lines output of any command-line tool into a CTIS report through a declarative mapping file, so a tool that writes JSON needs no parser code.

A mapping is a JSON document (apiVersion "openctem.io/mapping/v1"). Each rule selects input records with closed predicates and sets CTIS members from source paths with a closed set of transforms. The language has no expressions, loops, code or I/O: it cannot read files, reach the network or run for longer than the input it walks. A tool that keeps its mapping in YAML converts it to JSON before calling Load; the strict decoding here is the authority.

The full language is in docs/mapping.md.

Index

Constants

View Source
const (
	DefaultMaxInputBytes  = 64 << 20
	DefaultMaxRecordBytes = 1 << 20
	DefaultMaxRecords     = 200_000
	DefaultMaxOutputs     = 200_000
	DefaultMaxIssues      = 200
	MaxInputDepth         = 64
)

Default bounds of Apply.

View Source
const (
	MaxMappingBytes  = 256 << 10
	MaxRules         = 200
	MaxSetsPerRule   = 100
	MaxPredicates    = 16
	MaxRegexLen      = 256
	MaxMapEntries    = 256
	MaxInValues      = 256
	MaxTemplateBytes = 1024
)

Bounds on a mapping file.

View Source
const (
	SourceJSON  = "json"
	SourceJSONL = "jsonl"
)

Source formats.

View Source
const (
	KindAsset      = "asset"
	KindFinding    = "finding"
	KindDependency = "dependency"
)

Record kinds.

View Source
const APIVersion = "openctem.io/mapping/v1"

APIVersion is the only mapping format version this package reads.

Variables

View Source
var (
	ErrInputTooLarge = errors.New("mapping: input is larger than the limit")
	ErrNotAList      = errors.New("mapping: the each path does not name a list")
)

Errors of Apply.

Functions

This section is empty.

Types

type Issue

type Issue struct {
	// Record is the 1-based input record (the line for JSON Lines).
	Record int `json:"record"`
	// Rule is the index of the rule, or -1 for the record itself.
	Rule    int    `json:"rule"`
	Message string `json:"message"`
}

Issue is a record that was skipped or a rule output that was dropped.

func (Issue) String

func (i Issue) String() string

type Mapping

type Mapping struct {
	// contains filtered or unexported fields
}

Mapping is a loaded, validated mapping file.

func Load

func Load(data []byte) (*Mapping, error)

Load parses and validates a mapping file. Every error names the rule and member it is about.

func (*Mapping) Apply

func (m *Mapping) Apply(ctx context.Context, r io.Reader, opts Options) (*ctis.Report, Stats, error)

Apply reads the tool output from r and returns the CTIS report the mapping makes of it. Every rule whose predicates hold emits one record; a record that does not decode into its CTIS type or does not validate is skipped and counted. The output is deterministic for the same input, mapping and Options.Now.

A record limit or output limit ends the read early with Stats.Truncated set; an input larger than MaxInputBytes, a malformed json document or a canceled ctx returns an error and no report.

func (*Mapping) Digest

func (m *Mapping) Digest() string

Digest is the SHA-256 of the mapping's canonical JSON form ("sha256:<hex>"): object members sorted, insignificant whitespace removed. Reformatting or reordering a file keeps it; any change of content does not. A tool descriptor records it, so the mapping is covered by the descriptor's own digest.

func (*Mapping) Source

func (m *Mapping) Source() string

Source is the input format, "json" or "jsonl".

type Options

type Options struct {
	// Now is the report clock; nil means time.Now. Inject it for
	// reproducible output.
	Now func() time.Time
	// Tool is copied into report.tool. A mapping never sets it from the
	// input, so a tool's output cannot claim to be another tool.
	Tool *ctis.Tool

	MaxInputBytes  int64 // whole input; default 64 MiB
	MaxRecordBytes int   // one JSON Lines line; default 1 MiB
	MaxRecords     int   // input records read; default 200 000
	MaxOutputs     int   // assets + findings + dependencies; default 200 000
	MaxIssues      int   // Stats.Issues kept; default 200
}

Options bound and stamp one Apply.

type Predicate

type Predicate struct {
	Path    string `json:"path"`
	Exists  *bool  `json:"exists,omitempty"`
	Equals  any    `json:"equals,omitempty"`
	In      []any  `json:"in,omitempty"`
	Matches string `json:"matches,omitempty"`
}

Predicate is one closed condition on an input record. Exactly one of Exists, Equals, In and Matches is set.

type Predicates

type Predicates []Predicate

Predicates is "when": one predicate object or a list that must all hold.

func (*Predicates) UnmarshalJSON

func (p *Predicates) UnmarshalJSON(b []byte) error

UnmarshalJSON accepts an object or an array of objects.

type RuleSpec

type RuleSpec struct {
	When Predicates           `json:"when,omitempty"`
	Kind string               `json:"kind"`
	Set  map[string]ValueSpec `json:"set"`
}

RuleSpec is one rule as written in the file.

type Stats

type Stats struct {
	Records      int     `json:"records"`
	Assets       int     `json:"assets"`
	Findings     int     `json:"findings"`
	Dependencies int     `json:"dependencies"`
	Skipped      int     `json:"skipped"`
	Truncated    bool    `json:"truncated"`
	Issues       []Issue `json:"issues,omitempty"`
}

Stats count what Apply did.

type ValueSpec

type ValueSpec struct {
	Path     string            `json:"path,omitempty"`
	Const    any               `json:"const,omitempty"`
	Template string            `json:"template,omitempty"`
	Vars     map[string]string `json:"vars,omitempty"`
	Default  any               `json:"default,omitempty"`
	First    bool              `json:"first,omitempty"`
	Trim     bool              `json:"trim,omitempty"`
	Lower    bool              `json:"lower,omitempty"`
	Upper    bool              `json:"upper,omitempty"`
	Split    string            `json:"split,omitempty"`
	Map      map[string]string `json:"map,omitempty"`
	Join     *string           `json:"join,omitempty"`
	As       string            `json:"as,omitempty"`
	MaxBytes int               `json:"max_bytes,omitempty"`
	// contains filtered or unexported fields
}

ValueSpec is how one CTIS member gets its value: a bare string is a source path; an object takes exactly one of Path, Const and Template, then the transforms in this order: First, Trim, Lower, Upper, Split, Map, Join, As, MaxBytes. Default applies when the result is missing or empty.

func (ValueSpec) MarshalJSON

func (v ValueSpec) MarshalJSON() ([]byte, error)

MarshalJSON writes a bare path back as a string, so the digest of a mapping does not depend on which spelling its author used.

func (*ValueSpec) UnmarshalJSON

func (v *ValueSpec) UnmarshalJSON(b []byte) error

UnmarshalJSON accepts a bare path string or an object.

Jump to

Keyboard shortcuts

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