permission

package
v0.12.0 Latest Latest
Warning

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

Go to latest
Published: Aug 25, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package permission implements the single hardened workspace permission store defined by the access-profile specification.

The package owns three things and nothing else:

  • the schema-version-2 capability rule model and its strict JSON codec;
  • hardened loading of one explicit permission file (interactive read/write or headless read-only); and
  • atomic, interprocess-safe persistence of the exact displayed allow candidates after "Approve always for this workspace".

It does not parse tool arguments, decide Deny/Gated/Allow, or discover HOME. The harness gate evaluator consumes the Store structurally as its RuleMatcher and RuleWriter.

Index

Constants

View Source
const (
	CapabilityCommandExecute  = "command.execute"
	CapabilityNetwork         = "network"
	CapabilityFilesystemRead  = "filesystem.read"
	CapabilityFilesystemWrite = "filesystem.write"
)

Normalized capability kinds a rule may control. Filesystem and network kinds mirror the sandbox profile kinds; command execution reuses the harness constant value.

View Source
const (
	// ClassCommandInvoke matches one exact normalized command.
	ClassCommandInvoke = "command.invoke.v1"
	// ClassCommandInvokeWildcard is the stored representation of Bash(*).
	// It satisfies only the command-execution decision.
	ClassCommandInvokeWildcard = "command.invoke.wildcard.v1"
	// ClassCommandInvokeFamily is the token-prefix family (Bash(git log:*)).
	// This package stores and validates its shape; the token-aware segment
	// matcher plugs into matchesRequirement (match.go) without reshaping the
	// store.
	ClassCommandInvokeFamily = "command.invoke.shell-segment-glob.v1"
	// ClassNetworkTarget is target-scoped network access.
	ClassNetworkTarget = "network.target.v1"
	// ClassNetworkBroad is exact-command-bound broad egress (sandbox
	// grant class network.broad.v1).
	ClassNetworkBroad = "network.broad.v1"
	// Filesystem classes (sandbox grant-class identifiers).
	ClassFilesystemPathRead  = "filesystem.path.read.v1"
	ClassFilesystemPathWrite = "filesystem.path.write.v1"
	ClassFilesystemTreeRead  = "filesystem.tree.read.v1"
	ClassFilesystemTreeWrite = "filesystem.tree.write.v1"
	ClassFilesystemHostRead  = "filesystem.host.read.v1"
	ClassFilesystemHostWrite = "filesystem.host.write.v1"
)

Enforcement classes understood by schema version 2. Filesystem and broad network classes are aligned with the sandbox grant-class identifiers they correspond to; the command-invoke classes are gate-decision classes and the grant minted after a match is always the exact-command command.start.v1.

View Source
const (
	GrantClassCommandStart       = "command.start.v1"
	GrantClassNetworkProxyTarget = "network.proxy-target.v1"
)

Grant classes that appear on prepared requirements and persisted candidates. GrantClassCommandStart mirrors harness tool.GrantClassCommandStart; GrantClassNetworkProxyTarget is the sandbox target-scoped egress grant class.

View Source
const DefaultMaxFileBytes int64 = 1 << 20

DefaultMaxFileBytes is the default permission-file size bound.

View Source
const NormalizationVersion = 1

NormalizationVersion is the only supported match-normalization version. A file recording a different normalization version is unsupported: its rules were produced by an incompatible normalizer and must not match.

View Source
const SchemaVersion = 2

SchemaVersion is the only supported permission-file schema version.

Variables

This section is empty.

Functions

func BroadEgressMatch

func BroadEgressMatch(command, target string) string

BroadEgressMatch builds the canonical durable match string for one exact-command-bound broad egress delta.

func HostAccessMatch

func HostAccessMatch(command string) string

HostAccessMatch builds the canonical durable match string for one exact-command-bound broad host filesystem delta.

func NetworkTargetMatch

func NetworkTargetMatch(transport, host string, port int) string

NetworkTargetMatch builds the canonical durable match string for one normalized network target.

func NewReadOnlyStore

func NewReadOnlyStore(cfg Config) (*Store, []Diagnostic, error)

NewReadOnlyStore constructs the headless store. A configured path is loaded once as an immutable snapshot; a missing, malformed, insecure, oversized, or unsupported configured file fails startup. An empty path yields an empty rule set. The store never watches or reloads the file and rejects every write.

func NewWorkspaceStore

func NewWorkspaceStore(cfg Config) (*Store, []Diagnostic, error)

NewWorkspaceStore constructs the interactive read/write store for one workspace permission file. The file may not exist yet; an existing file must be secure and well-formed or construction fails. The returned diagnostics are the non-fatal findings of the initial load.

func ProposeCommandCandidate

func ProposeCommandCandidate(command string, eligible FamilyEligibility) string

ProposeCommandCandidate returns the reusable command-candidate match string Bash preparation should display for one normalized command: a family candidate "Bash(tokens:*)" when the command is a single supported simple segment whose longest bare literal token prefix is in the injected eligibility catalog, and the exact normalized command otherwise. Unknown prefixes, shells, interpreters, execution wrappers, multi-segment commands, and unsupported syntax all fall back to the exact command because the positive catalog decides; bare Bash(*) is never proposed.

A command whose own text collides with the Bash(...) rule-syntax namespace (see collidesWithBashRuleSyntax) gets NO reusable candidate — the empty string. An exact fallback for such a command would be re-read by the store as a wildcard or family rule, so a malicious literal command `Bash(*)` (a mere shell syntax error when run) could otherwise be laundered into a durable allow-everything record via `Approve always`. Refusal is chosen over an escaped encoding because the candidate Match doubles as the exact display text; once-only approval is unaffected, and a user who truly wants a durable exact rule for such a command can author the structured command.invoke.v1 file record, which is unambiguous.

func TreeMatch

func TreeMatch(root string) string

TreeMatch builds the canonical durable match string for one configured tree root.

Types

type Config

type Config struct {
	// Path is the one explicit permission-file path. Interactive stores
	// require it; a read-only store with an empty Path uses an empty rule
	// set. The store never discovers HOME or any other implicit location.
	Path string
	// MaxFileBytes bounds the permission file size. Zero selects
	// DefaultMaxFileBytes.
	MaxFileBytes int64
	// FamilyEligible is the consumer's automatic-family eligibility catalog
	// predicate, used only to produce non-fatal diagnostics for manual
	// out-of-catalog allow families. Nil treats every allow family as out of
	// catalog. It never alters matching.
	FamilyEligible FamilyEligibility
}

Config configures one Store.

type Diagnostic

type Diagnostic struct {
	Code      DiagnosticCode
	RuleIndex int    // index of the rule in the loaded file
	Message   string // bounded, non-secret description
}

Diagnostic is one non-fatal finding produced while loading rules. It is reported separately from fatal file errors and never alters rule precedence.

type DiagnosticCode

type DiagnosticCode string

DiagnosticCode classifies one non-fatal rule diagnostic.

const DiagnosticAllowFamilyOutOfCatalog DiagnosticCode = "allow_family_out_of_catalog"

DiagnosticAllowFamilyOutOfCatalog reports a manually authored, syntactically valid allow family whose token prefix is outside the consumer's automatic eligibility catalog. The rule remains authoritative; the consumer must surface the diagnostic. Deny families never warn.

type Effect

type Effect string

Effect is the decision a rule contributes. Deny always beats allow.

const (
	EffectAllow Effect = "allow"
	EffectDeny  Effect = "deny"
)

The two rule effects.

type FamilyEligibility

type FamilyEligibility func(tokens []string) bool

FamilyEligibility reports whether an allow family with the given literal token prefix belongs to the consumer's explicit automatic-proposal catalog. The catalog itself is product policy and is injected by the consumer; a nil predicate treats every allow family as out of catalog.

type FileError

type FileError struct {
	Path   string
	Reason FileErrorReason
	Err    error
}

FileError is the typed fatal failure for loading or writing one permission file. Non-fatal rule diagnostics are reported separately as Diagnostic values, never as FileError.

func (*FileError) Error

func (e *FileError) Error() string

func (*FileError) Unwrap

func (e *FileError) Unwrap() error

type FileErrorReason

type FileErrorReason string

FileErrorReason classifies a fatal permission-file failure.

const (
	FileMalformed          FileErrorReason = "malformed"
	FileVersionUnsupported FileErrorReason = "version_unsupported"
	FileRuleInvalid        FileErrorReason = "rule_invalid"
	FileNotRegular         FileErrorReason = "not_regular"
	FileSymlink            FileErrorReason = "symlink"
	FileOwnerUnexpected    FileErrorReason = "owner_unexpected"
	FileModeUnexpected     FileErrorReason = "mode_unexpected"
	FileLinkCount          FileErrorReason = "link_count_unexpected"
	FileTooLarge           FileErrorReason = "too_large"
	FileMissing            FileErrorReason = "missing"
	FileIO                 FileErrorReason = "io"
	FileLock               FileErrorReason = "lock"
	FileReadOnly           FileErrorReason = "read_only"
	FileCandidateInvalid   FileErrorReason = "candidate_invalid"
)

Fatal file-failure reasons. Hardening reasons are produced by the store; schema reasons by this codec.

type Rule

type Rule struct {
	Effect     Effect
	Capability string
	Class      string

	// ClassCommandInvoke: the exact normalized command.
	// ClassNetworkBroad, ClassFilesystemHost{Read,Write}: the exact
	// normalized command the broad delta is bound to.
	Command string

	// ClassCommandInvokeFamily.
	Tokens            []string
	TrailingArguments bool

	// ClassNetworkTarget. Host is required; Transport and Port are optional
	// constraints, and omitting one deliberately broadens the rule.
	Transport string
	Host      string
	Port      int

	// ClassNetworkBroad: the backend enforcement target (for example a port
	// class) the broad delta was approved for.
	Target string

	// ClassFilesystemPath{Read,Write}: one canonical absolute path.
	Path string

	// ClassFilesystemTree{Read,Write}: one canonical absolute root.
	Root string
}

Rule is one normalized capability record. Exactly the fields belonging to its enforcement class are populated; the strict codec rejects any other combination so a wildcard or family command record can never carry a filesystem or network delta.

type RuleError

type RuleError struct {
	Index  int // position in the file or candidate batch, -1 when unknown
	Reason string
}

RuleError reports one invalid rule at load or write time. Loading a file containing an invalid rule fails: silently dropping an explicit consumer record could widen (dropped deny) or misrepresent (dropped allow) policy.

func (*RuleError) Error

func (e *RuleError) Error() string

type Store

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

Store is the hardened workspace permission store.

func (*Store) Diagnostics

func (s *Store) Diagnostics() []Diagnostic

Diagnostics returns the non-fatal rule diagnostics of the most recent load. Diagnostics are reported separately from fatal file errors and never alter rule precedence.

func (*Store) MatchesAllow

func (s *Store) MatchesAllow(ctx context.Context, requirement tool.Requirement) (bool, error)

MatchesAllow reports whether any stored allow rule matches the requirement.

func (*Store) MatchesDeny

func (s *Store) MatchesDeny(ctx context.Context, requirement tool.Requirement) (bool, error)

MatchesDeny reports whether any stored deny rule matches the requirement. Any load failure fails closed as an error; the gate rejects the call.

func (*Store) WriteRules

func (s *Store) WriteRules(ctx context.Context, candidates []tool.RuleCandidate) error

WriteRules atomically appends the complete displayed allow-candidate batch to the workspace file. It locks the workspace, re-reads and merges under the lock, writes an owner-only temporary file, fsyncs it, renames it into place, and fsyncs the directory. Any failure leaves the prior complete file intact and returns an error, so the approved call is blocked rather than silently downgraded to a once-only approval.

Jump to

Keyboard shortcuts

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