approval

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package approval implements the manifest approval state machine: the hard part of mcp-shield isn't hashing JSON, it's deciding "is this capability change acceptable?" and never letting that decision be bypassed or silently reversed.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNotPending        = errors.New("approval: manifest is not in PENDING state")
	ErrInvalidTransition = errors.New("approval: invalid state transition")
)

Functions

This section is empty.

Types

type CheckResult

type CheckResult struct {
	ManifestID int64
	State      string
	Warn       bool // failMode is warn: everything is allowed, this is advisory only

	SafeTools     map[string]bool
	SafePrompts   map[string]bool
	SafeResources map[string]bool
}

CheckResult reports the gate's decision for one manifest snapshot. A manifest that is not fully APPROVED is no longer all-or-nothing: tools (and prompts/resources) that are byte-identical to the current approved baseline stay in Safe* and keep working, while only the new or changed ones are withheld pending a decision. A server with no approved baseline at all (first-ever connect) has empty Safe* sets, which is the fail closed starting state.

type FailMode

type FailMode string

FailMode controls what happens when traffic hits an unapproved manifest.

const (
	// FailModeBlock refuses traffic for any non-APPROVED manifest. Default.
	FailModeBlock FailMode = "block"
	// FailModeWarn allows traffic through but flags it as unapproved. Only
	// meant for initial rollout/observation, never the production default.
	FailModeWarn FailMode = "warn"
)

type Option added in v0.1.1

type Option func(*Workflow)

Option adjusts optional workflow behaviour. Zero options is the plain gate, unchanged.

func WithNotifications added in v0.1.1

func WithNotifications() Option

WithNotifications makes the workflow record a notification event in the same transaction as each state change it writes, so an operator can be told that a capability was withheld.

The workflow's involvement ends there. It writes a row; it never learns where events go, never waits for one, and cannot fail because of one. All this option can cost a gate decision is one INSERT into a transaction that was already open.

type Workflow

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

func New

func New(store database.Store, failMode FailMode, opts ...Option) *Workflow

func (*Workflow) Approve

func (w *Workflow) Approve(ctx context.Context, manifestID int64, username, reason string) error

Approve marks a PENDING manifest APPROVED, supersedes the server's previous APPROVED manifest (if any), and records an immutable audit entry — all inside one transaction.

func (*Workflow) CheckAndRecord

func (w *Workflow) CheckAndRecord(ctx context.Context, serverID int64, m *manifest.Manifest) (*CheckResult, error)

CheckAndRecord is the gate: given a live manifest fetched from an upstream server, it looks up (or creates) the matching manifest row and computes which tools/prompts/resources are safe to expose right now.

  • Hash matches the current APPROVED baseline exactly -> everything safe.
  • Otherwise (hash is PENDING/REJECTED/SUPERSEDED, or new) -> only the subset unchanged from the current approved baseline is safe; new or changed items are withheld. A brand new manifest row is inserted (diffed against the baseline) the first time a given hash is seen; a hash seen before just reuses its existing row/state.
  • failMode warn overrides withholding: everything is marked safe, Warn is set, but the manifest's real state is still recorded as-is.

func (*Workflow) Reject

func (w *Workflow) Reject(ctx context.Context, manifestID int64, username, reason string) error

Reject marks a PENDING manifest REJECTED and records an immutable audit entry. Traffic for that manifest hash remains blocked; the row is never deleted or reused.

Jump to

Keyboard shortcuts

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