Help us shape the future of Go! Take the 2026 Go Developer Survey

check

package
v1.0.0-rc.12 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2026 License: Apache-2.0 Imports: 26 Imported by: 0

Documentation

Overview

Package check judges a declared check against a source tree.

A check is a declared expectation — what must hold, how it is judged (sh, tool, llm, runtime), how severe a failure is, and whether it is about a state of the tree or a transition one change made. Evaluating one needs the declaration, a source tree and three capabilities: run a command in a container, ask a model a checklist, probe a URL. None of that is a project, an adoption, a Change or a review, so none of it is AppTown's: this package knows nothing of AppTown and could be lifted into another program (design/architecture/layout.md, "When something becomes a library"); scripts/shape-check.py's standalone rule holds it to that.

AppTown subsystem internal/apptown/conformance wraps records and decisions around it: which declaration a project adopted, whose exception excuses a finding, what the gate decides over head and base, and what a review recorded.

Index

Constants

View Source
const (
	AppliesRepository = "repository"
	AppliesPart       = "part"
	AppliesBuild      = "build"
	AppliesStatic     = "static"
	AppliesContainer  = "container"
)

Applicability. A check declares what it applies to (Declaration.AppliesTo, Scanner.AppliesTo) in words about the app's declared parts, and the judge decides before anything runs whether it applies: never the check's own script searching the tree. A check that applies to nothing is NotApplicable with the reason; one that applies runs once per folder of the parts it matches, and finding nothing to judge there is the check's failure, since the declaration and the code disagree.

The words:

repository  once, at the repository root, when the tree holds any file
part        any part
build       a part built from a folder's Dockerfile
static      a part served as files
container   a part run as a container
tool:<name> a part built with that tool

A part matches when it matches any of the words; repository stands alone.

View Source
const (
	KindBuild     = "build"
	KindStatic    = "static"
	KindContainer = "container"
)

Part kinds, as Part.Kinds lists them.

View Source
const (
	ScopeTree = "tree"
	ScopeDiff = "diff"
)

Check scopes.

View Source
const BrowserEnvPath = "/_apptown/env.js"

BrowserEnvPath is the file a static part's server answers with the values AppTown gives its page (window.__APPTOWN_ENV__).

View Source
const ChecklistSystem = `` /* 550-byte string literal not displayed */

ChecklistSystem is the prompt template. Its hash is part of the evaluator identity, so an edited template is a changed evaluator.

View Source
const DefaultMemoryWithin = 90

DefaultMemoryWithin is memory-within's share when the probe names none.

View Source
const PackingVersion = "pack-v2"

PackingVersion changes whenever the packing algorithm below changes — exclusions, caps, ordering, truncation markers. It is part of every AI verdict's evaluator identity.

View Source
const PartFolderVar = "${PART_FOLDER}"

PartFolderVar in a tool's command is the folder it runs in, as the container sees it: /work for the repository root, /work/<folder> for a part's.

View Source
const ScanTimeout = 5 * time.Minute

ScanTimeout bounds one scanner run.

View Source
const ShTimeout = 60 * time.Second

ShTimeout bounds one check's script.

Variables

View Source
var HTTPFetcher = FetcherFunc(func(ctx context.Context, url string) (int, string, error) {
	resp, err := probeClient.Get(url)
	if err != nil {
		return 0, "", err
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
	return resp.StatusCode, string(body), err
})

HTTPFetcher is the real fetcher: a plain GET, redirects unfollowed, the body read up to a megabyte.

View Source
var HTTPProber = ProberFunc(func(_ context.Context, url string) (int, error) {
	resp, err := probeClient.Get(url)
	if err != nil {
		return 0, err
	}
	resp.Body.Close()
	return resp.StatusCode, nil
})

HTTPProber is the real prober: a plain GET, redirects unfollowed.

ProbeTransport is the transport every probe of an app uses: a pool of its own, so a boot's checks still reuse one connection, but one that nothing else in the process closes. A connection pooled on http.DefaultTransport is closed under the probe whenever anything calls CloseIdleConnections on it (every httptest.Server.Close does), and the probe read that as an app that gave no answer. It trusts the deployments use (internal/trust): a preview's or a deployment's address may be signed by a company's proxy or by a desktop trial's own authority.

Functions

func AppliesHere

func AppliesHere(words []string, src Source) (string, error)

AppliesHere is the decision for a check judged once for the whole app (a rubric, a runtime probe): "" when it applies to some declared part (or the repository), else the reason it is not applicable.

func AppliesToPublic

func AppliesToPublic(words []string, src Source) (string, error)

AppliesToPublic is the decision for a check that looks at the public part's image (an image or exec-image scanner): the public part must run as a container, and match the words.

func AppliesTools

func AppliesTools(words []string) []string

AppliesTools names the tools a list of words names.

func BundleHash

func BundleHash(s string) string

func EmptyExitDetail

func EmptyExitDetail(scanner string, pl Place) string

EmptyExitDetail is what a scanner's nothing-to-judge exit says where the scanner applies.

func Evaluator

func Evaluator(c Declaration) string

Evaluator is the single default rule used by validation, descriptions and execution. Explicit declarations win; inferred declarations retain publication precedence (script, rubric, scanner, runtime probe).

func Evaluators

func Evaluators() []string

Evaluators is every evaluator kind a declaration may name. Validate admits exactly these, so a caller that judges declared checks can be held to judging each kind.

func FailsAt

func FailsAt(failOn, severity string) bool

FailsAt says whether a finding of severity fails a scan whose failOn is failOn: every finding when failOn is empty, otherwise one ranked at or above it. It is the one meaning of a scan's failOn; a policy ceiling (wow.FailOnLooseness) orders thresholds by it.

func FindingsSummary

func FindingsSummary(tool string, fs []Finding) string

FindingsSummary names the top findings so a reader sees WHAT, not a count.

func Fingerprint

func Fingerprint(id Identity, check, file string) string

Fingerprint is the stable finding identity shared by gates and review exceptions. Dispositions on a live instance match on it: it does not change.

func IsPostureSh

func IsPostureSh(c Declaration) bool

IsPostureSh / IsRuntime classify an expectation's evaluation mode.

func IsRuntime

func IsRuntime(c Declaration) bool

func JudgedAtLanding

func JudgedAtLanding(c Declaration) bool

JudgedWhere says, in words, where a check is judged — the catalog shows it. JudgedAtLanding says whether a landing can judge the check, so a change can be accepted on it. A runtime check answered only by a standing deployment's steady use is skipped at every landing: no change can prove it, and it is never a change's acceptance.

func JudgedWhere

func JudgedWhere(c Declaration) string

func LLMEvaluatorVersion

func LLMEvaluatorVersion(c Declaration) string

LLMEvaluatorVersion is the evaluator identity of an AI check: packing version, template hash, and the hash of the rubric and its file globs. A changed rubric, file list, template or packing is a changed evaluator.

func ModeFor

func ModeFor(c Declaration) string

func NakedRefusal

func NakedRefusal(code, expect int, summary string) string

NakedRefusal names the cause a header-less probe most likely hit, so the finding tells the fixing agent what to exempt. A redirect is the HTTPS redirect; a 403 is a host allow-list refusing a request that arrived by address (Rails config.hosts, Django ALLOWED_HOSTS); anything else is reported as what it is.

func OccurrenceLines

func OccurrenceLines(out string) []string

OccurrenceLines splits a check's output into its occurrences: one per non-blank line, trimmed, duplicates kept (two identical lines are two occurrences — the baseline matches them one for one).

func PackEvidence

func PackEvidence(src string, globs []string) (bundle string, files []string, err error)

PackEvidence collects the files matching globs under src, deterministically (sorted relative paths; excluded dirs, except files a glob names exactly, symlinks, binaries and minified files skipped; per-file and per-rubric caps with explicit markers), and returns the bundle text plus the list of files it contains. A file or directory that cannot be read is the error: a bundle without it would be judged as if it were the whole evidence.

func PageRefusal

func PageRefusal(status int, path string) string

PageRefusal says why a front-page answer means a visitor cannot use the app, or "" when it does not: any server error, and the two ways a host allow-list refuses a host it was never told (Django's DisallowedHost is 400, Rails host authorization 403). Any other answer means the app answered: a 401 or a redirect to sign in is a working front page, and a 404 is an API-only app with nothing at its root (greeting-api, pulse-api).

func PartFolderPath

func PartFolderPath(folder string) string

PartFolderPath is the folder's path in the container.

func PostureScript

func PostureScript(c Declaration) (string, bool)

PostureScript returns an expectation's committed-tree sh script and whether it supports posture mode at all. An llm-only rubric has no posture mode.

func ProbePage

func ProbePage(ctx context.Context, p PageProbe) (status int, path string, err error)

ProbePage GETs the app's root as a visitor would and returns the status it ends on and the path that answered. Redirects on the same origin are followed (to the same address, with the same host and headers); one that leaves the origin (a sign-in provider) is the answer as it stands.

func RemoveStale

func RemoveStale(path string) error

RemoveStale removes what an earlier run left at path (a report, a verdict) before a run that will write it: a file there afterwards is then this run's. Already absent is fine; a removal that fails is the error, since the old bytes would read as this run's answer.

func ReportLost

func ReportLost(name string) string

ReportLost is the detail of a check that failed and whose report, what it printed, did not arrive: a container's stdout can be lost at its end. It says the report is gone, never that nothing was found.

func SARIFMessageField

func SARIFMessageField(text, label string) string

SARIFMessageField: "Label: value" out of a multi-line SARIF message.

func Scope

func Scope(c Declaration) string

Scope resolves a check's scope with the defaults of §2.1.

func SeverityRank

func SeverityRank(s string) int

SeverityRank orders severities for failOn thresholds. Unknown ranks as high: a finding nobody scored is not a finding you may silently ship. A note was scored, as the lowest level a check declaration may take.

func TemplateHash

func TemplateHash() string

func ToolSummary

func ToolSummary(tool, output string) string

ToolSummary trims a tool's raw output to a one-glance detail line. It is only asked of a tool that failed, so no output is a lost report.

func ValidToolName

func ValidToolName(s string) bool

ValidToolName is the spelling a tool name has, in appliesTo and in a contract's part tools.

func Validate

func Validate(checks []Declaration) error

Validate normalizes and checks a set of declarations, filling the defaults (evaluator, scope, severity) in place.

func ValidateAppliesTo

func ValidateAppliesTo(words []string) error

ValidateAppliesTo checks a declared list of words. Tool names are only checked for their spelling here: which tools exist is the caller's.

Types

type BrowserExpectation

type BrowserExpectation struct {
	Static bool
	// Attached is what the page must be given: the integration settings as
	// they are now.
	Attached map[string]string
	// Installed is what the running container was started with, read from the
	// container itself; nil when that could not be established.
	Installed map[string]string
}

BrowserExpectation is what the caller knows from trusted sources, not from the response being judged: whether the app's contract serves a static site, what the project's integrations give its page now, and what the running container was given when it started.

type ChecklistMeta

type ChecklistMeta struct {
	Served     string // the model the provider actually served
	PromptHash string
	Items      int
	Cost       float64
	Tokens     Tokens
	ParseError bool
	Retried    bool // the answer was asked for twice: the first was not JSON
}

ChecklistMeta is what a call records about itself.

type Completer

type Completer interface {
	Complete(ctx context.Context, system, user string) (Completion, error)
}

Completer asks a model for one answer.

type CompleterFunc

type CompleterFunc func(ctx context.Context, system, user string) (Completion, error)

CompleterFunc adapts a function to Completer.

func (CompleterFunc) Complete

func (f CompleterFunc) Complete(ctx context.Context, system, user string) (Completion, error)

type Completion

type Completion struct {
	Text   string
	Model  string // the model the provider actually served
	Tokens Tokens
	Cost   float64
}

Completion is one answer from the model, as the caller's adapter observed it. What it cost and whose budget it lands on stay with the caller.

type Declaration

type Declaration struct {
	Name      string `json:"name"`
	Title     string `json:"title,omitempty"`     // authored action title for a remediation; identity remains Name
	Expects   string `json:"expects"`             // one plain sentence: what conformance looks like
	Severity  string `json:"severity,omitempty"`  // note|low|medium|high (default note)
	Evaluator string `json:"evaluator,omitempty"` // sh|llm|runtime|tool (default sh when sh set, llm when rubric set, tool when tool set)
	Sh        string `json:"sh,omitempty"`
	Rubric    string `json:"rubric,omitempty"`
	Probe     string `json:"probe,omitempty"` // runtime evaluator: a probe against the booted app
	Tool      string `json:"tool,omitempty"`  // tool evaluator: names a scanner binding to run (design/subsystems/conformance.md §13)
	// Scope says what the check is ABOUT (design/subsystems/conformance-surface.md §2):
	// "tree" — a state of the committed tree, judged at the gate AND in every
	// fleet review; "diff" — a transition made by one change, judged at the gate
	// only. sh/tool/runtime are always tree. An llm rubric defaults to diff (the
	// meaning every existing block version has) and may declare tree, in which
	// case Files names the evidence the rubric is judged on.
	Scope string   `json:"scope,omitempty"`
	Files []string `json:"files,omitempty"`
	// Occurrences says how the check reports WHAT it found: "lines" — one
	// occurrence per output line, so a gate can tell a pre-existing finding
	// from a new one (design/subsystems/ways-of-working-versions.md §4.2). Unset: the
	// check is boolean; failing on both trees is "regression unknown".
	Occurrences string `json:"occurrences,omitempty"`
	// AppliesTo says what the check applies to, in words about the app's
	// declared parts (applies.go). Required: a check that applies to no
	// declared part is not applicable, never a pass on nothing.
	AppliesTo []string `json:"appliesTo,omitempty"`
}

Declaration is what must hold and how it is judged. The JSON tags are the authored form: a way of working carries its checks in this shape.

func ParseDeclarations

func ParseDeclarations(raw string) ([]Declaration, error)

ParseDeclarations reads authored check declarations (a JSON array) and validates them: a key a declaration does not have is refused, so a misspelt field is an error, never a check silently judged without it. Stored declarations were read this way when saved.

type Declared

type Declared struct {
	Identity
	Declaration
}

Declared is one declaration with the identity that declares it.

type Evaluation

type Evaluation struct {
	Declared
	Mode        Mode
	Outcome     Outcome
	Detail      string
	Findings    []Finding
	Occurrences []string
	Evidence    Evidence
	// Fault: the judge failed, not the tree. A change must never be sent back
	// to its author over one.
	Fault bool
}

Evaluation is one declaration against one source in one mode.

func Judgement

func Judgement(it Item, v Verdict, answered bool, meta *ChecklistMeta, mode Mode) Evaluation

Judgement is what one checklist answer means for the item it answered: the verdict words are the checklist's, the outcome is the judge's. answered says the checklist returned anything at all for this item — an item it passed over is cannot-assess, since silence is not a pass. meta, when given, records what the call cost and what prompt it was.

func NotApplicableHere

func NotApplicableHere(d Declared, src Source, mode Mode) *Evaluation

NotApplicableHere is the evaluation of a check judged once for the app when it does not apply, or nil when it does (an error is the check's error, never a pass).

type Evidence

type Evidence struct {
	EvaluatorVersion string // the identity a verdict keys on; unchanged strings
	Hash             string // hash of the evidence bundle judged
	PromptHash       string // model calls only
	Report           string // the report a tool wrote and the judge read; "" = none
	Image            string // the image (by ID) an exec-image check ran in; "" = none
	Files            []string
	Output           string
	ExitCode         *int
	Duration         time.Duration
	Tokens           Tokens
}

Evidence is what the judge recorded about HOW it judged: the evaluator's own identity, the hash of the exact material it looked at, and its output.

type Fetcher

type Fetcher interface {
	Fetch(ctx context.Context, url string) (int, string, error)
}

Fetcher gets a URL's status and body.

type FetcherFunc

type FetcherFunc func(ctx context.Context, url string) (int, string, error)

FetcherFunc adapts a function to Fetcher.

func (FetcherFunc) Fetch

func (f FetcherFunc) Fetch(ctx context.Context, url string) (int, string, error)

type Finding

type Finding struct {
	Fingerprint string      `json:"fingerprint"`
	Kind        string      `json:"kind"`     // vuln | secret | sast | license
	Severity    string      `json:"severity"` // critical|high|medium|low|unknown
	Identifiers []string    `json:"identifiers,omitempty"`
	Package     *PackageRef `json:"package,omitempty"`
	Location    *Location   `json:"location,omitempty"`
	Title       string      `json:"title"`
	Detail      string      `json:"detail,omitempty"`
	URL         string      `json:"url,omitempty"`
	Source      string      `json:"source"` // binding name
	// Reached: osv-scanner call analysis — does the program actually call the
	// vulnerable code? nil = no data. VEX-grade context: an unreached vuln is
	// the textbook not_affected justification. Never changes the verdict by
	// itself; dispositions stay a human act.
	Reached *bool `json:"reached,omitempty"`
	// Items: the occurrences a conformance check reported (one per line when
	// the check declares occurrences: lines), so a gate can subtract what
	// already fails on the base tree and count only what is new.
	Items []string `json:"items,omitempty"`
}

func Normalize

func Normalize(format string, report []byte, source, kind string) ([]Finding, error)

Normalize turns a scanner's native report into findings. The error says why nothing came back — an unknown format, or a report that would not parse; the gate ignores it the way it always has (no findings is the answer either way) and a self-service run can say what went wrong.

type Identity

type Identity struct {
	Namespace string
	Version   int
}

Identity names whoever declared a check, opaquely: AppTown passes the block and the version the project adopted. The library only prints it.

type Item

type Item struct {
	Declared
	Scope    string // tree | diff
	Evidence string // packed files for tree; "" for diff (the shared diff is attached once)
	Files    []string
	Hash     string // hash of the exact evidence this item is judged on
	// Unreadable says why the item's evidence could not be read: it is not
	// put to the model, and its judgement is cannot-assess.
	Unreadable string
}

Item is one rubric with the evidence it is judged on.

func DiffItems

func DiffItems(checks []Declared, diff string) []Item

DiffItems lists every diff-scoped rubric; they share one diff.

func TreeItems

func TreeItems(checks []Declared, src string) []Item

TreeItems packs every tree-scoped rubric's evidence from src, applying the batch-level cap in order (later rubrics lose their evidence first, marked).

type Judge

type Judge struct {
	// Run executes one container. The caller supplies it rather than a bare
	// execution.Runner because a host adds its own cache mounts, labels and
	// ownership to every run it owns.
	Run func(execution.Request) execution.Outcome
	// ShImage is the image sh checks run in, the tool versions' shell, from
	// the snapshot the caller's unit of work took. "": they error.
	ShImage string
	// Complete asks a model for one answer. nil: rubrics cannot be assessed.
	Complete Completer
	// Probe makes one HTTP request. nil: runtime checks cannot be assessed.
	Probe Prober
	// Scanners resolves a tool check's name to the tool it names. nil: tool
	// checks cannot be assessed.
	Scanners Scanners
	// RunImage runs a command INSIDE an already-built image, with nothing
	// mounted: the exec-image self-check, which must see the app as the app
	// sees itself. nil: those checks cannot be assessed.
	RunImage func(image string, argv, env []string) (exitCode int, output string)
	// Readiness resolves what path a `readiness` probe means for this source —
	// the app's own declaration, which only the caller can read. nil or false:
	// the check reports does-not-conform, as an app that is served while
	// declaring nothing about when it is ready has not met the way of working.
	Readiness func(src Source) (string, bool)
	// NamePrefix names the containers a run owns, so a host can find them.
	NamePrefix string
	// Now is the judge's clock, for how long an evaluation took; nil is the
	// real clock.
	Now func() time.Time
}

A Judge holds the three capabilities evaluating a check can need: run a command in a container, ask a model a checklist, probe a URL. A capability it was not given is not an error — the checks that need it report cannot-assess with the reason.

func (*Judge) Checklist

func (j *Judge) Checklist(ctx context.Context, items []Item, diff string) (map[int]Verdict, *ChecklistMeta, error)

Checklist makes the ONE call for a set of items and returns verdicts by item number (1-based). diff is attached once when any item is diff-scoped. A failed call returns err; the caller records the items as skipped with the reason — conformance never depends on a model being up.

An item whose evidence could not be read (Unreadable) is left out of the prompt, keeping every other item's number; with none left, no call is made.

func (*Judge) Evaluate

func (j *Judge) Evaluate(ctx context.Context, checks []Declared, src Source, mode Mode) ([]Evaluation, error)

Evaluate judges every declaration against one source, in one mode.

sh: one container run per check against the staged tree. llm: every rubric in the batch into ONE checklist call, prompt hash and evidence hash recorded. runtime: probe the source's app through both doors. tool: the scanner the check names, from the catalogue the caller gave the judge.

A capability the judge or the source lacks is cannot-assess with the reason, never an error: the tree is not at fault for what the judge could not do.

func (*Judge) EvaluateSh

func (j *Judge) EvaluateSh(checks []Declared, src Source, mode Mode, namePrefix string) []Evaluation

EvaluateSh judges every sh check in the batch against the staged tree, one container run each.

func (*Judge) EvaluateTool

func (j *Judge) EvaluateTool(d Declared, src Source, mode Mode, namePrefix string) Evaluation

EvaluateTool judges one tool check: the named scanner against the source, or inside the image the source names.

Evaluation.Findings are what the TOOL reported, itemised and normalized — not a roll-up of the check. A caller that excuses individual findings (a recorded exception, a verified false positive) applies that to them and decides what the check then says.

type Judged

type Judged struct {
	Evaluation
	Provenance  Provenance
	Own         []Finding
	PreExisting []Finding
}

Judged is one head evaluation with its provenance: the findings it carries as the base leaves them (an introduced finding names only what is new), split into what this tree introduced and what the base already reported. A finding that can be neither — a boolean check failing on both trees, with no occurrences to compare — is in neither list, and the provenance says Undecided: a reader judges the diff.

func Classify

func Classify(head, base []Evaluation, baseKnown bool) []Judged

Classify judges every head evaluation against what the base tree reported. One rule serves both kinds of finding, because the difference is in what a fingerprint identifies:

  • A DECLARED CHECK's finding stands for the whole check, so the same fingerprint on the base says only "this check fails there too". The occurrences decide: the ones not on the base are this tree's, and a check with no occurrences to compare is Undecided.

  • Any other finding — a scanner's — identifies the problem itself, so the base reporting the same fingerprint is proof the problem was already there (carriedScans).

  • A check that judges one property of the whole app and reports no occurrences — a probe of the running app, a model's verdict on a rubric — is PreExisting when the base fails it too: the property was already broken there, and there is nothing to count that the change could have added to. (A shell check without occurrences stays Undecided: its author could have asked it to list what it found.)

  • A declared check the base could not be judged on (a base evaluation of it that is cannot-assess: main's deployment runs another commit, the model did not answer) leaves its head finding Undecided: nothing says whether the change introduced it, and the caller names why.

baseKnown says the base was evaluated at all: without it nothing can be subtracted and every finding is the head's (Introduced). What the base commit is, whether it is on the protected branch, and which checks are judged absolutely whatever the base says, are the caller's facts — established before the base evaluations are handed over.

type Location

type Location struct {
	File string `json:"file"`
	Line int    `json:"line,omitempty"`
}

type Mode

type Mode int

Mode is what the evaluation is asked to say: a Gate judges one change's proposed tree, a Posture sweep judges a committed tree as it stands.

const (
	Gate Mode = iota
	Posture
)

func (Mode) String

func (m Mode) String() string

type Outcome

type Outcome int

Outcome is what a judge can say on its own. NotApplicable is decided from the check's declared applicability before anything runs; a person's decisions over an outcome (excepted) are the caller's.

const (
	Conforms Outcome = iota + 1
	DoesNotConform
	CannotAssess // not mechanically answerable, or the source lacks the capability
	Error        // the evaluator failed, timed out, or returned malformed output
	// NotApplicable: the check applies to nothing this app declares
	// (Applies); never a pass and never an error. Detail is the reason.
	NotApplicable
)

func JudgePage

func JudgePage(ctx context.Context, frontDoor string) (Outcome, string)

JudgePage asks the front page through the front door: refused is a finding, no answer is the review's inability to look, not the app's fault.

func ProbeBothDoors

func ProbeBothDoors(ctx context.Context, p Prober, frontDoor, naked string, ps ProbeSpec) (state Outcome, detail string)

ProbeBothDoors judges a path through the front door and naked. Both must answer the expected status: the front door because that is what serves, naked because that is what any header-less probe sees (§5.2).

func (Outcome) String

func (o Outcome) String() string

type PackageRef

type PackageRef struct {
	Name      string `json:"name"`
	Version   string `json:"version,omitempty"`
	Ecosystem string `json:"ecosystem,omitempty"`
	FixedIn   string `json:"fixedIn,omitempty"`
}

type PageProbe

type PageProbe struct {
	URL     string
	Host    string
	Headers map[string]string
}

PageProbe is one front-page request: the address the app is asked at, and the host name and headers a visitor's request carries through the front door. An empty Host leaves the address's own.

type Part

type Part struct {
	Name string
	// Folder is the part's folder relative to the repository root ("." for
	// the root); "" for a part with none (a pulled image), which is judged
	// at the root.
	Folder string
	Kinds  []string // KindBuild, KindStatic, KindContainer
	Tools  []string // what the part is built with
	Public bool
}

Part is one part of the app as its contract declares it, in the terms applicability reads. The caller derives it from its own contract.

type Place

type Place struct {
	Folder string   // relative to the repository root; "." is the root
	Parts  []string // sorted; nil for a repository run
}

Place is one folder a check runs in and the parts judged there.

func Applies

func Applies(words []string, src Source) ([]Place, string, error)

Applies is the one applicability decision: the folders a check with these words runs in, or the reason it is not applicable (no places), or the error that makes it unjudgeable (a contract that could not be read).

type ProbeSpec

type ProbeSpec struct {
	Path       string
	Expect     int
	Readiness  bool // resolve the path from the contract's declared readiness
	BrowserEnv bool // judge the page against AppTown's /_apptown/env.js
	Page       bool // judge the front page through the front door (JudgePage)
	// MemoryDeclared judges the contract, not the running app.
	MemoryDeclared bool
	// MemoryWithin is the share of its applied limit, in percent, a part of
	// the standing deployment must stay under; 0 when the probe is another.
	MemoryWithin int
}

ProbeSpec is a parsed `probe` field.

func ParseProbe

func ParseProbe(s string) (ProbeSpec, error)

func (ProbeSpec) NeedsApp

func (ps ProbeSpec) NeedsApp() bool

NeedsApp says the probe is answered by a running app. memory-declared is answered by the contract alone, so the gate judges it with no preview.

func (ProbeSpec) Standing

func (ps ProbeSpec) Standing() bool

Standing says the probe is answered only by a standing deployment: what AppTown applied to it and observed of it. A freshly booted preview has no steady use to judge, so the gate skips it.

type ProbeVerdict

type ProbeVerdict struct {
	Outcome Outcome
	Detail  string
	Fault   bool
}

ProbeVerdict is a probe's verdict and, when the verdict is unknown, whether AppTown is answerable for it: Fault means AppTown could not supply or establish what the check depends on, so no change to the app could make it pass. A change must never be sent back to its author over one.

func JudgeBrowserEnv

func JudgeBrowserEnv(ctx context.Context, f Fetcher, base string, want BrowserExpectation) ProbeVerdict

JudgeBrowserEnv judges a running app at base: a static site whose integrations give its page values must have been started with exactly those, must serve exactly what it was started with in /_apptown/env.js, and its HTML must load that file by the supported convention. A server app is not judged. Conforming says the values are served and the markup loads them first; it does not say a browser ran the script (a content security policy can still stop it) or that reporting works.

Why: a static app can adopt error reporting, pass review and ship, and never report, because nothing put the DSN in its page. The judgment is strict because looser ones were fooled: a mention of the path, a <base href>, a template and nomodule must not pass for a loader, and an AppTown delivery fault must be cannot-assess, never a pass or rework for the app.

type Prober

type Prober interface {
	Probe(ctx context.Context, url string) (int, error)
}

Prober makes one probe request and reports the status it got.

type ProberFunc

type ProberFunc func(ctx context.Context, url string) (int, error)

ProberFunc adapts a function to Prober.

func (ProberFunc) Probe

func (f ProberFunc) Probe(ctx context.Context, url string) (int, error)

type Provenance

type Provenance int

Provenance: how a finding on the head tree reads against the base tree the change forked from (design/subsystems/ways-of-working-versions.md §4.2). A change is judged on what IT did; what already failed on the base is the estate's. Which commit is the base, and whether it is on the protected branch, are facts the caller establishes and passes in.

const (
	Introduced  Provenance = iota // the change introduced it, or the base cannot say otherwise
	PreExisting                   // every occurrence was already on the base
	Undecided                     // fails on both trees with no occurrence evidence, or the base could not be judged: unknowable here
)

func (Provenance) String

func (p Provenance) String() string

type Scanner

type Scanner struct {
	Name        string   `yaml:"name" json:"name"`
	Description string   `yaml:"description" json:"description"`
	Image       string   `yaml:"image" json:"image"`
	Command     []string `yaml:"command" json:"command"`
	Report      string   `yaml:"report" json:"report"`
	Network     bool     `yaml:"network" json:"network"`
	// Format enables the structured-findings layer (findings.md): osv | sarif.
	// Empty = exit-code contract only. Kind labels SARIF findings (secret|sast|license).
	Format string `yaml:"format" json:"format"`
	Kind   string `yaml:"kind" json:"kind"`
	// ArtifactKind overrides the report artifact's kind (default scan-report);
	// e.g. "sbom" for syft — evidence of what shipped, not findings.
	ArtifactKind string `yaml:"artifactKind" json:"artifactKind"`
	// Target: what the scanner looks at — "source" (the committed tree,
	// default), "image" (the app's built container image, handed over
	// as a saved tarball at /work/.apptown/image.tar; use ${IMAGE_TAR} in
	// the command), or "exec-image" (run the command INSIDE the app's built
	// image — a framework self-check that must import settings;
	// design/subsystems/conformance.md §13.5). Scan POINTS in system workflows
	// (`with: {on: image}`) expand to every attached scanner with the matching
	// target (design/decisions/workflows-as-lanes.md).
	Target string `yaml:"target" json:"target"`
	// HistoryCommand: a source scanner that can read Git history checks,
	// at a landing, every commit the landing brings to the default branch,
	// not only its final tree: this command runs instead of Command, with
	// the project's repository mounted read-only at /history and
	// ${HISTORY_RANGE} naming those commits (target..candidate). A secret
	// added in one commit and removed in the next still lands in history,
	// which only a history scan sees.
	HistoryCommand []string `yaml:"historyCommand" json:"historyCommand"`
	// Manual: this scanner is invoked ONLY by name (a way-of-working `tool`
	// check, design/subsystems/conformance.md §13), never auto-expanded at a scan point.
	// It keeps a way-of-working-specific tool (a Django linter) from firing
	// fleet-wide the way a universal scanner (gitleaks) does.
	Manual bool `yaml:"manual" json:"manual"`
	// NoEntrypoint clears the image's entrypoint, so Command (and
	// HistoryCommand) is the whole command: a networked scanner whose image starts its program directly
	// runs the extra certificates' script first (internal/trust) with
	// ["sh", "-c", "eval \"${APPTOWN_TRUST:-}\"; exec \"$@\"", "sh", <program>, ...].
	NoEntrypoint bool `yaml:"noEntrypoint" json:"noEntrypoint"`
	// AppliesTo is what a scan-point scanner applies to (applies.go),
	// required for one that is not manual; a manual scanner takes the
	// applicability of the check that names it and declares none.
	AppliesTo []string `yaml:"appliesTo" json:"appliesTo,omitempty"`
	// EmptyExit is the exit the tool gives when it found nothing to judge
	// (osv-scanner's 128, "no package sources found"). Where the scanner
	// applies, that is a failure: the contract says there is something to
	// judge. 0: the tool has no such exit.
	EmptyExit int `yaml:"emptyExit" json:"emptyExit,omitempty"`
}

func (Scanner) Looks

func (s Scanner) Looks() string

Looks says what the scanner looks at, with "source" as the default.

func (Scanner) Request

func (s Scanner) Request(workspace string, argv []string) execution.Request

Request is the scanner's run over workspace with argv (its Command, or HistoryCommand, its variables filled in): its image, with its entrypoint cleared when it says so, the network only when it needs it, and the scan timeout. Every place that runs a scanner starts from it, so what the manifest says reaches the container the same way everywhere.

func (Scanner) ValidateApplicability

func (s Scanner) ValidateApplicability() error

ValidateApplicability holds a manifest to its applicability rule: a scanner that is not manual states what it applies to; a manual one does not, since the check that names it does.

type Scanners

type Scanners interface {
	Scanner(name string) (Scanner, bool)
}

Scanners is the catalogue a tool check's name is looked up in. Resolving a name to an attached, configured tool is the caller's: the judge only asks.

type ScannersFunc

type ScannersFunc func(name string) (Scanner, bool)

ScannersFunc makes a catalogue out of one lookup.

func (ScannersFunc) Scanner

func (f ScannersFunc) Scanner(name string) (Scanner, bool)

type Source

type Source struct {
	Tree  string // a read-only checkout of the exact commit; the caller stages it
	SHA   string
	Diff  string // for diff-scoped rubrics; "" in a review
	Image string // built app image reference for exec-image tools; "" = not available
	// Env is what an exec-image tool runs with: the environment of a deployed
	// app, derived by the caller from what the app declares.
	Env []string
	App string // base URL of a booted app for runtime probes; "" = not available
	// Naked: the same app reached by address with no front-door signal. "" when
	// only one door is reachable.
	Naked string
	// What applicability reads (applies.go): the app's declared parts,
	// whether the tree holds no file, whether there is no contract at all,
	// a contract that could not be read, and the folders the contract says
	// are not the app's code.
	Parts      []Part
	Empty      bool
	NoContract bool
	PartsErr   error
	NotAppCode []string
}

Source is the material an evaluation judges. A capability the source lacks is cannot-assess with the reason, never an error.

type Tokens

type Tokens struct {
	Input  int64
	Output int64
}

Tokens is what a model call cost, as the judge observed it. What that means in money, and whose budget it lands on, is the caller's business.

type Verdict

type Verdict struct {
	Item     int    `json:"item"`
	Verdict  string `json:"verdict"`
	Evidence string `json:"evidence"`
	Note     string `json:"note"`
}

Verdict is one item's parsed answer.

func ParseChecklist

func ParseChecklist(out string) ([]Verdict, error)

ParseChecklist reads the judge's answer as a JSON array of verdicts, tolerating a code fence around it.

Jump to

Keyboard shortcuts

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