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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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).