safety

package
v0.4.5 Latest Latest
Warning

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

Go to latest
Published: Jun 19, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package safety implements the runtime safety rails for destructive, administrative, and raw-write tool calls: confirmation-token issuance and validation (TokenStore), risk-class policy lookup (RequirementForRisk), and canonical-JSON hashing used to bind a confirmation token to the exact argument payload that previewed it (HashCanonical).

Index

Constants

View Source
const DefaultTokenTTL = 5 * time.Minute

DefaultTokenTTL is the default lifetime of a confirmation token issued by TokenStore.Issue when TokenStoreOptions.TTL is unset or non-positive. Short enough that a stale preview cannot be confirmed out-of-band; long enough for an operator to read the dry-run result and decide whether to proceed.

Variables

This section is empty.

Functions

func HashCanonical

func HashCanonical(v any) string

HashCanonical returns a hex-encoded SHA-256 of v after stripping non-deterministic fields ("confirm_token", "dry_run") and recursively normalising map/slice contents. The resulting digest is stable across equivalent argument shapes so a confirmation-token preview hash can be matched against a follow-up call's arguments byte-for-byte.

func TokenAuditSuffix

func TokenAuditSuffix(token string) string

TokenAuditSuffix returns a short SHA-256-derived suffix that uniquely identifies a confirmation token in audit logs without exposing the token's secret bytes. 12 hex chars (48 bits) is enough to distinguish concurrent tokens in a single-user store while keeping log noise minimal.

Types

type Payload

type Payload struct {
	ToolName    string
	WorkspaceID string
	RiskClass   string
	ArgsHash    string
	PreviewHash string
}

Payload is the immutable per-call identity bound into a confirmation token. Equality of all five fields is required for TokenStore.Validate to accept the token, so any drift between dry-run and confirm (different workspace, args, or preview) invalidates the token rather than silently executing the wrong operation.

type Requirement

type Requirement struct {
	RequiresDryRun       bool
	RequiresConfirmation bool
	Reason               string
}

Requirement captures the safety preconditions a tool call must satisfy before it can be executed. RequiresDryRun forces the caller to first run with dry_run=true so the user previews the operation; RequiresConfirmation forces a follow-up call carrying a confirmation token bound to the dry-run preview. Reason explains which classifier triggered the requirement and is surfaced to the MCP client in the recovery envelope.

func RequirementForRisk

func RequirementForRisk(riskNames []string, destructive bool, method string) Requirement

RequirementForRisk classifies a tool call's safety needs from its declared risk labels, destructive flag, and (for raw fallback) HTTP method. Raw DELETE/POST/PUT/PATCH always require both dry-run and confirmation. Destructive tools always require both. Tools tagged billing, admin, permission_change, or external_side_effect require confirmation (dry-run only when also destructive). All other risk labels are passthrough.

type TokenStore

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

TokenStore issues single-use confirmation tokens bound to a Payload and rejects re-use, expiry, or payload mismatch. Safe for concurrent use; tokens are held only in memory (the single-user stdio product does not persist them across restarts).

func NewTokenStore

func NewTokenStore(opts TokenStoreOptions) *TokenStore

NewTokenStore returns a ready-to-use TokenStore with the given options. TTL defaults to DefaultTokenTTL when zero or negative; Now defaults to time.Now when nil.

func (*TokenStore) Issue

func (s *TokenStore) Issue(payload Payload) (token, previewHash string, expiresAt time.Time, err error)

Issue generates a new confirmation token bound to payload and returns the token string, the canonical preview hash of the payload, and the absolute expiry. Callers include the token in the dry-run response and the preview hash in the audit log so a follow-up confirm call can be matched against the original preview. Returns an error when the underlying CSPRNG fails.

func (*TokenStore) Validate

func (s *TokenStore) Validate(token string, payload Payload) error

Validate consumes token if it was issued for an identical payload and has not expired. The token is removed atomically so any subsequent Validate call with the same string fails — a confirmation token is single-use. Returns an error when the token is unknown, expired, or bound to a different payload.

type TokenStoreOptions

type TokenStoreOptions struct {
	TTL time.Duration
	Now func() time.Time
}

TokenStoreOptions configures TokenStore. TTL overrides the default token lifetime (see DefaultTokenTTL). Now is the clock source used for issue/expire computations; nil falls back to time.Now (tests inject a fake clock here).

Jump to

Keyboard shortcuts

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