trust

package
v0.2.4 Latest Latest
Warning

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

Go to latest
Published: Jul 28, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package trust decides whether the devvault-managed files inside a repository may be used to run something on the host.

devvault clones repositories the user does not control, and then hands repository-owned files to `docker compose` and `container build`. Those files decide mounts, privileges and build steps, so they are exactly the inputs that must not be trusted blindly.

The rule is: a managed file is trustworthy when it is byte-identical to what devvault would render from the trusted config, or when the user approved its current content. Approvals live in the user-owned registry under ~/.devvault, never in the repository — a repository can never approve itself.

Index

Constants

This section is empty.

Variables

View Source
var ErrDiffTooLarge = fmt.Errorf("file is too large to diff")

ErrDiffTooLarge reports that a file is too large to diff line by line.

Functions

func Digests

func Digests(report Report) map[string]string

Digests returns the digests observed in a report, ready to be stored as approvals. Missing files contribute nothing.

func RecordAfterGenerate

func RecordAfterGenerate(root, projectID string) error

RecordAfterGenerate stores the digests of the files devvault just generated, so the very next command does not stop at a file devvault wrote itself. A directory without a registry entry has nowhere to store approvals; that is not an error, it only means the files have to keep matching their templates.

Only the managed target paths are recorded, never a repository-supplied fallback such as ./docker-compose.yml — generating files must not turn pre-existing repository content into approved content.

func Require

func Require(root string, cfg config.Config, approved map[string]string) error

Require returns an actionable error when an enforced file of the project at root is neither generated nor approved.

func RequireProject

func RequireProject(root string, cfg config.Config, projectID string) error

RequireProject is the enforcement entry point of every command that runs something inside the container.

func UnifiedDiff

func UnifiedDiff(path, repoContent, generated string) (string, error)

UnifiedDiff renders the difference between the file the repository ships and the file devvault would generate, in unified diff format. It returns ErrDiffTooLarge when a side exceeds the review limits.

Types

type FileStatus

type FileStatus struct {
	// Path is the repository-relative path of the file devvault actually
	// found, which for a fallback candidate differs from Expected.
	Path string
	// Expected is the repository-relative path devvault manages.
	Expected string
	State    State
	// Enforced reports whether drift in this file blocks execution.
	Enforced bool
	// Digest is "sha256:<hex>" of the current content, empty when missing.
	Digest string
	// MatchesTemplate reports whether the content on disk is byte-identical to
	// what devvault would render from the trusted config right now. It answers
	// a different question than State: State is the security verdict — did
	// anything change since devvault generated the file or the user approved
	// it — while MatchesTemplate is the consistency one: does the file still
	// follow the config. The two come apart after a config change: a file that
	// carries an approval stays StateOK because nothing was smuggled into it,
	// but it no longer matches the config, and `devvault sync` is the way back.
	//
	// It is false wherever devvault has no rendered content for the path it
	// found, so it reads as "not known to follow the config", never as "known
	// to differ": a missing file, a repository-supplied fallback such as
	// ./docker-compose.yml or .devcontainer/Dockerfile, and every unexpected
	// entry inside .devvault/scripts. HasTemplate tells those apart from a real
	// mismatch.
	MatchesTemplate bool
}

FileStatus is the verdict for one managed file of a project.

func (FileStatus) HasTemplate added in v0.2.2

func (f FileStatus) HasTemplate() bool

HasTemplate reports whether MatchesTemplate is the outcome of an actual comparison. It is true exactly for a managed file that exists at the path devvault manages, and false where nothing could be compared — see MatchesTemplate.

type ProjectReport

type ProjectReport struct {
	Report
	// Project is the registry key, empty for a directory that is not
	// registered.
	Project string
	// Registered reports whether devvault has a place to store approvals for
	// this directory.
	Registered bool
}

ProjectReport adds the registry project the approvals belong to.

func Accept

func Accept(root string, cfg config.Config, projectID string) (ProjectReport, error)

Accept stores the digests currently found in the repository as approvals. This is a deliberate security decision by the user; callers must confirm it first.

func InspectProject

func InspectProject(root string, cfg config.Config, projectID string) (ProjectReport, error)

InspectProject inspects root using the approvals stored for projectID. An empty projectID falls back to the project registered for root, if any.

type Report

type Report struct {
	Files []FileStatus
	// Trusted is false as soon as one enforced file drifted or is unmanaged.
	Trusted bool
}

Report is the verdict for a whole project.

func Inspect

func Inspect(root string, cfg config.Config, approved map[string]string) (Report, error)

Inspect classifies every managed file of the project at root. cfg must be the trusted config (see projectcontext.LoadTrustedConfig); approved maps repository-relative paths to digests the user approved.

func (Report) Stale added in v0.2.2

func (r Report) Stale() bool

Stale reports whether at least one managed file no longer matches what devvault would render from the trusted config — the state a `devvault tools bump` or a hand-edited `.devvault/config.yaml` leaves behind. It is deliberately independent of Trusted: a file that has not changed since the user approved it keeps its approval and blocks nothing, it has merely fallen behind the config. `devvault sync` regenerates it.

type ReviewItem

type ReviewItem struct {
	File FileStatus
	// Diff is a unified diff between the repository content and the content
	// devvault would generate. It is empty when Note explains why there is
	// none.
	Diff string
	// Note replaces the diff when comparing is impossible or pointless.
	Note string
	// Size is the size of the repository file in bytes.
	Size int64
	// Approved reports that this exact content carries the user's approval and
	// only fell behind the config. The diff below is then not evidence that
	// someone changed the file — it is what `devvault sync` would write.
	Approved bool
}

ReviewItem is what the user has to look at for one file that is neither generated nor approved.

func Review

func Review(root string, cfg config.Config, report Report) ([]ReviewItem, error)

Review collects the files a user has to look at before approving anything, plus the approved ones that no longer match the config: the diff against the freshly rendered template is exactly what a user wants to see before running `devvault sync`.

The content of an unmanaged file is never echoed: devvault would run it, but it is repository-owned data and printing it raw is how a crafted file reaches the terminal.

type State

type State string

State is the verdict for a single managed file.

const (
	// StateOK means the file matches a freshly rendered template or an
	// approved digest.
	StateOK State = "ok"
	// StateDrifted means the file exists where devvault manages it, but its
	// content is neither generated nor approved.
	StateDrifted State = "drifted"
	// StateMissing means devvault did not find the file. Missing files never
	// block: the backends fail with their own, more precise message.
	StateMissing State = "missing"
	// StateUnmanaged means devvault would use a file outside the managed
	// layout — a repository-supplied fallback such as ./docker-compose.yml.
	// Such a file can never match a template and always needs an approval.
	StateUnmanaged State = "unmanaged"
)

type UntrustedError

type UntrustedError struct {
	// Project is the registry key used in the suggested commands.
	Project string
	// Registered reports whether an approval could be stored at all.
	Registered bool
	Files      []FileStatus
}

UntrustedError explains which files stopped devvault and what to do about them. The paths it names are devvault's own managed paths and fallback candidates — compile-time constants, never strings taken from the repository.

func (*UntrustedError) Error

func (e *UntrustedError) Error() string

Jump to

Keyboard shortcuts

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