difc

package
v0.1.14 Latest Latest
Warning

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

Go to latest
Published: Mar 11, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ModeStrict    = "strict"
	ModeFilter    = "filter"
	ModePropagate = "propagate"
)

DIFC mode string constants - use these for consistent mode references

Variables

ValidModes contains all valid DIFC enforcement mode strings

Functions

func FormatViolationError

func FormatViolationError(result *EvaluationResult, agentSecrecy *SecrecyLabel, agentIntegrity *IntegrityLabel, resource *LabeledResource) error

FormatViolationError creates a detailed error message explaining the violation and its implications

Types

type AccessDecision

type AccessDecision int

AccessDecision represents the result of a DIFC evaluation

const (
	AccessAllow AccessDecision = iota
	AccessDeny
	// AccessAllowWithPropagate indicates access is allowed but requires label propagation
	AccessAllowWithPropagate
)

func (AccessDecision) String

func (a AccessDecision) String() string

type AgentLabels

type AgentLabels struct {
	AgentID   string
	Secrecy   *SecrecyLabel
	Integrity *IntegrityLabel
	// contains filtered or unexported fields
}

AgentLabels associates each agent with their DIFC labels Tracks what secrecy and integrity tags an agent has accumulated

func NewAgentLabels

func NewAgentLabels(agentID string) *AgentLabels

NewAgentLabels creates a new agent with empty labels

func NewAgentLabelsWithTags

func NewAgentLabelsWithTags(agentID string, secrecyTags []Tag, integrityTags []Tag) *AgentLabels

NewAgentLabelsWithTags creates a new agent with initial tags

func (*AgentLabels) AccumulateFromRead

func (a *AgentLabels) AccumulateFromRead(resource *LabeledResource)

AccumulateFromRead updates agent labels after reading data in propagate mode

DIFC propagate mode semantics:

  • Secrecy: UNION - agent becomes "tainted" with all secret classifications from the data Agent secrecy = Union(agent_secrecy, resource_secrecy) Reading secret data means the agent now carries that secret classification

  • Integrity: INTERSECTION - agent's trustworthiness is reduced to the minimum Agent integrity = Intersection(agent_integrity, resource_integrity) Reading from untrusted sources reduces agent's integrity to the lowest common denominator

func (*AgentLabels) AddIntegrityTag

func (a *AgentLabels) AddIntegrityTag(tag Tag)

AddIntegrityTag adds an integrity tag to the agent

func (*AgentLabels) AddIntegrityTags added in v0.1.14

func (a *AgentLabels) AddIntegrityTags(tags []Tag)

AddIntegrityTags adds multiple integrity tags to the agent

func (*AgentLabels) AddSecrecyTag

func (a *AgentLabels) AddSecrecyTag(tag Tag)

AddSecrecyTag adds a secrecy tag to the agent

func (*AgentLabels) AddSecrecyTags added in v0.1.10

func (a *AgentLabels) AddSecrecyTags(tags []Tag)

AddSecrecyTags adds multiple secrecy tags to the agent

func (*AgentLabels) ApplyPropagation added in v0.1.10

func (a *AgentLabels) ApplyPropagation(result *EvaluationResult) bool

ApplyPropagation applies label changes from a propagate-mode evaluation result This adds missing secrecy tags and drops missing integrity tags Returns true if any labels were changed

func (*AgentLabels) Clone

func (a *AgentLabels) Clone() *AgentLabels

Clone creates a copy of the agent labels

func (*AgentLabels) DropIntegrityTag

func (a *AgentLabels) DropIntegrityTag(tag Tag)

DropIntegrityTag removes an integrity tag from the agent

func (*AgentLabels) DropIntegrityTags added in v0.1.10

func (a *AgentLabels) DropIntegrityTags(tags []Tag)

DropIntegrityTags removes multiple integrity tags from the agent

func (*AgentLabels) GetIntegrityTags

func (a *AgentLabels) GetIntegrityTags() []Tag

GetIntegrityTags returns a copy of integrity tags (thread-safe)

func (*AgentLabels) GetSecrecyTags

func (a *AgentLabels) GetSecrecyTags() []Tag

GetSecrecyTags returns a copy of secrecy tags (thread-safe)

type AgentRegistry

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

AgentRegistry manages agent labels across all agents

func NewAgentRegistry

func NewAgentRegistry() *AgentRegistry

NewAgentRegistry creates a new agent registry

func NewAgentRegistryWithDefaults

func NewAgentRegistryWithDefaults(defaultSecrecy []Tag, defaultIntegrity []Tag) *AgentRegistry

NewAgentRegistryWithDefaults creates a registry with default labels for new agents

func (*AgentRegistry) Count

func (r *AgentRegistry) Count() int

Count returns the number of registered agents

func (*AgentRegistry) Get

func (r *AgentRegistry) Get(agentID string) (*AgentLabels, bool)

Get retrieves an agent's labels if they exist

func (*AgentRegistry) GetAllAgentIDs

func (r *AgentRegistry) GetAllAgentIDs() []string

GetAllAgentIDs returns all registered agent IDs

func (*AgentRegistry) GetOrCreate

func (r *AgentRegistry) GetOrCreate(agentID string) *AgentLabels

GetOrCreate gets an existing agent or creates a new one with default labels

func (*AgentRegistry) Register

func (r *AgentRegistry) Register(agentID string, secrecyTags []Tag, integrityTags []Tag) *AgentLabels

Register creates a new agent with specific initial labels

func (*AgentRegistry) Remove

func (r *AgentRegistry) Remove(agentID string)

Remove removes an agent from the registry

func (*AgentRegistry) SetDefaultLabels

func (r *AgentRegistry) SetDefaultLabels(secrecy []Tag, integrity []Tag)

SetDefaultLabels sets the default labels for new agents

type Capabilities

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

Capabilities represents the global set of tags available in the system This is used to validate and discover available DIFC tags

func NewCapabilities

func NewCapabilities() *Capabilities

NewCapabilities creates a new empty capabilities set

func (*Capabilities) Add

func (c *Capabilities) Add(tag Tag)

Add adds a tag to the capabilities

func (*Capabilities) AddAll

func (c *Capabilities) AddAll(tags []Tag)

AddAll adds multiple tags to the capabilities

func (*Capabilities) Clear

func (c *Capabilities) Clear()

Clear removes all tags from the capabilities

func (*Capabilities) Contains

func (c *Capabilities) Contains(tag Tag) bool

Contains checks if a tag is available in the capabilities

func (*Capabilities) Count

func (c *Capabilities) Count() int

Count returns the number of available tags

func (*Capabilities) GetAll

func (c *Capabilities) GetAll() []Tag

GetAll returns all available tags

func (*Capabilities) Remove

func (c *Capabilities) Remove(tag Tag)

Remove removes a tag from the capabilities

type CollectionLabeledData

type CollectionLabeledData struct {
	Items []LabeledItem
}

CollectionLabeledData represents a collection where each item has its own labels

func (*CollectionLabeledData) Overall

func (c *CollectionLabeledData) Overall() *LabeledResource

func (*CollectionLabeledData) ToResult

func (c *CollectionLabeledData) ToResult() (interface{}, error)

type EnforcementMode added in v0.1.10

type EnforcementMode int

EnforcementMode determines how DIFC policy violations are handled

const (
	// EnforcementStrict blocks any access that violates DIFC rules
	// This is the default mode for strong security guarantees
	EnforcementStrict EnforcementMode = iota

	// EnforcementFilter allows reads but filters out inaccessible items from collections
	// Writes that violate DIFC rules are still blocked
	EnforcementFilter

	// EnforcementPropagate allows reads by automatically adjusting agent labels:
	// - If agent lacks secrecy clearance for a resource, the missing secrecy tags
	//   are added to the agent's secrecy label (agent becomes "tainted" with secret data)
	// - If resource lacks integrity tags that agent has, those integrity tags
	//   are removed from the agent's integrity label (agent is "influenced" by untrusted data)
	// Writes that violate DIFC rules are still blocked (no propagation for writes)
	EnforcementPropagate
)

func ParseEnforcementMode added in v0.1.10

func ParseEnforcementMode(s string) (EnforcementMode, error)

ParseEnforcementMode parses a string into an EnforcementMode

func (EnforcementMode) String added in v0.1.10

func (m EnforcementMode) String() string

type EvaluationResult

type EvaluationResult struct {
	Decision        AccessDecision
	SecrecyToAdd    []Tag  // Secrecy tags agent must add to proceed
	IntegrityToDrop []Tag  // Integrity tags agent must drop to proceed
	Reason          string // Human-readable reason for denial
}

EvaluationResult contains the decision and required label changes

func (*EvaluationResult) IsAllowed

func (e *EvaluationResult) IsAllowed() bool

IsAllowed returns true if access is allowed (either directly or with propagation)

func (*EvaluationResult) RequiresPropagation added in v0.1.10

func (e *EvaluationResult) RequiresPropagation() bool

RequiresPropagation returns true if access requires label propagation

type Evaluator

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

Evaluator performs DIFC policy evaluation

func NewEvaluator

func NewEvaluator() *Evaluator

NewEvaluator creates a new DIFC evaluator with strict enforcement mode

func NewEvaluatorWithMode added in v0.1.10

func NewEvaluatorWithMode(mode EnforcementMode) *Evaluator

NewEvaluatorWithMode creates a new DIFC evaluator with the specified enforcement mode

func (*Evaluator) Evaluate

func (e *Evaluator) Evaluate(
	agentSecrecy *SecrecyLabel,
	agentIntegrity *IntegrityLabel,
	resource *LabeledResource,
	operation OperationType,
) *EvaluationResult

Evaluate checks if an agent can perform an operation on a resource

func (*Evaluator) FilterCollection

func (e *Evaluator) FilterCollection(
	agentSecrecy *SecrecyLabel,
	agentIntegrity *IntegrityLabel,
	collection *CollectionLabeledData,
	operation OperationType,
) *FilteredCollectionLabeledData

FilterCollection filters a collection based on agent labels Returns accessible items and filtered items separately

func (*Evaluator) GetMode added in v0.1.10

func (e *Evaluator) GetMode() EnforcementMode

GetMode returns the current enforcement mode

func (*Evaluator) SetMode added in v0.1.10

func (e *Evaluator) SetMode(mode EnforcementMode)

SetMode sets the enforcement mode

type FieldLabels

type FieldLabels struct {
	Secrecy   *SecrecyLabel
	Integrity *IntegrityLabel

	// Predicate is an optional function to determine labels based on field value
	// For example: label repo as private if repo.Private == true
	Predicate func(value interface{}) (*SecrecyLabel, *IntegrityLabel)
}

FieldLabels defines labels for a specific field in the response

type FilteredCollectionLabeledData

type FilteredCollectionLabeledData struct {
	Accessible   []LabeledItem
	Filtered     []LabeledItem
	TotalCount   int
	FilterReason string
}

FilteredCollectionLabeledData represents a collection with some items filtered out

func (*FilteredCollectionLabeledData) GetAccessibleCount

func (f *FilteredCollectionLabeledData) GetAccessibleCount() int

GetAccessibleCount returns the number of accessible items

func (*FilteredCollectionLabeledData) GetFilteredCount

func (f *FilteredCollectionLabeledData) GetFilteredCount() int

GetFilteredCount returns the number of filtered items

func (*FilteredCollectionLabeledData) Overall

func (*FilteredCollectionLabeledData) ToResult

func (f *FilteredCollectionLabeledData) ToResult() (interface{}, error)

type IntegrityLabel

type IntegrityLabel struct {
	Label *Label
}

IntegrityLabel wraps Label with integrity-specific flow semantics Integrity flow: data can flow from high integrity to low integrity l ⊇ target (this has all tags that target has)

func NewIntegrityLabel

func NewIntegrityLabel() *IntegrityLabel

NewIntegrityLabel creates a new empty integrity label

func NewIntegrityLabelWithTags

func NewIntegrityLabelWithTags(tags []Tag) *IntegrityLabel

NewIntegrityLabelWithTags creates an integrity label with the given tags

func (*IntegrityLabel) CanFlowTo

func (l *IntegrityLabel) CanFlowTo(target *IntegrityLabel) bool

CanFlowTo checks if this integrity label can flow to target Integrity semantics: l ⊇ target (this has all tags that target has) For writes: agent must have >= integrity than endpoint For reads: endpoint must have >= integrity than agent

func (*IntegrityLabel) CheckFlow

func (l *IntegrityLabel) CheckFlow(target *IntegrityLabel) (bool, []Tag)

CheckFlow checks if this integrity label can flow to target and returns violation details if not

func (*IntegrityLabel) Clone

func (l *IntegrityLabel) Clone() *IntegrityLabel

Clone creates a copy of the integrity label

type Label

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

Label represents a set of DIFC tags

func NewLabel

func NewLabel() *Label

NewLabel creates a new empty label

func (*Label) Add

func (l *Label) Add(tag Tag)

Add adds a tag to this label

func (*Label) AddAll

func (l *Label) AddAll(tags []Tag)

AddAll adds multiple tags to this label

func (*Label) Clone

func (l *Label) Clone() *Label

Clone creates a copy of this label

func (*Label) Contains

func (l *Label) Contains(tag Tag) bool

Contains checks if this label contains a specific tag

func (*Label) GetTags

func (l *Label) GetTags() []Tag

GetTags returns all tags in this label as a slice

func (*Label) Intersect added in v0.1.10

func (l *Label) Intersect(other *Label)

Intersect removes tags from this label that are not in the other label After this operation, this label contains only tags present in both labels

func (*Label) IsEmpty

func (l *Label) IsEmpty() bool

IsEmpty returns true if this label has no tags

func (*Label) Remove added in v0.1.10

func (l *Label) Remove(tag Tag)

Remove removes a single tag from this label

func (*Label) RemoveAll added in v0.1.10

func (l *Label) RemoveAll(tags []Tag)

RemoveAll removes multiple tags from this label

func (*Label) Union

func (l *Label) Union(other *Label)

Union merges another label into this label

type LabeledData

type LabeledData interface {
	// Overall returns the aggregate labels for all data
	Overall() *LabeledResource

	// ToResult converts the labeled data to an MCP result
	// This may filter out inaccessible items
	ToResult() (interface{}, error)
}

LabeledData represents response data with associated labels Used for fine-grained filtering in the reference monitor

type LabeledItem

type LabeledItem struct {
	Data   interface{}
	Labels *LabeledResource
}

LabeledItem represents a single item in a collection with its labels

type LabeledResource

type LabeledResource struct {
	Description string         // Human-readable description of the resource
	Secrecy     SecrecyLabel   // Secrecy requirements for this resource
	Integrity   IntegrityLabel // Integrity requirements for this resource

	// Structure is an optional nested map for fine-grained labeling of response fields
	// Maps JSON paths to their labels (e.g., "items[*].private" -> specific labels)
	// If nil, labels apply uniformly to entire resource
	Structure *ResourceStructure
}

LabeledResource represents a resource with DIFC labels This can be a simple label pair or a complex nested structure for fine-grained filtering

func NewLabeledResource

func NewLabeledResource(description string) *LabeledResource

NewLabeledResource creates a new labeled resource with the given description

type OperationType

type OperationType int

OperationType indicates the nature of the resource access

const (
	OperationRead OperationType = iota
	OperationWrite
	OperationReadWrite
)

func (OperationType) String

func (o OperationType) String() string

type PathLabel added in v0.1.10

type PathLabel struct {
	// Path is a JSON Pointer (RFC 6901) to the element
	// Examples: "/items/0", "/results/5", "/data/users/0"
	Path string `json:"path"`

	// Labels for this path
	Labels PathLabelEntry `json:"labels"`
}

PathLabel associates a JSON Pointer path with DIFC labels

type PathLabelEntry added in v0.1.10

type PathLabelEntry struct {
	Description string   `json:"description,omitempty"`
	Secrecy     []string `json:"secrecy"`
	Integrity   []string `json:"integrity"`
}

PathLabelEntry contains the DIFC labels for a path

type PathLabeledData added in v0.1.10

type PathLabeledData struct {
	// OriginalData is the unmodified response from the backend
	OriginalData interface{}

	// UnwrappedData is the data to apply paths against (may be unwrapped from MCP format)
	UnwrappedData interface{}

	// IsMCPWrapped indicates if the original data was MCP-wrapped
	IsMCPWrapped bool

	// PathLabels contains the guard's labeling decisions
	PathLabels *PathLabels
	// contains filtered or unexported fields
}

PathLabeledData implements LabeledData for path-based labels. It combines the original response data with path labels from the guard.

func NewPathLabeledData added in v0.1.10

func NewPathLabeledData(originalData interface{}, pathLabels *PathLabels) (*PathLabeledData, error)

NewPathLabeledData creates a new PathLabeledData from the original response and path labels. It automatically detects and unwraps MCP-formatted responses ({"content":[{"text":"..."}]}) so that path labels can be applied to the inner JSON structure.

func (*PathLabeledData) GetItems added in v0.1.10

func (p *PathLabeledData) GetItems() []LabeledItem

GetItems returns the resolved labeled items for filtering

func (*PathLabeledData) Overall added in v0.1.10

func (p *PathLabeledData) Overall() *LabeledResource

Overall returns the aggregate labels for all items

func (*PathLabeledData) ToCollectionLabeledData added in v0.1.10

func (p *PathLabeledData) ToCollectionLabeledData() *CollectionLabeledData

ToCollectionLabeledData converts to CollectionLabeledData for compatibility with existing filtering

func (*PathLabeledData) ToResult added in v0.1.10

func (p *PathLabeledData) ToResult() (interface{}, error)

ToResult returns the original data (path labels don't modify the data structure)

type PathLabels added in v0.1.10

type PathLabels struct {
	// LabeledPaths maps JSON Pointer paths (RFC 6901) to their labels
	LabeledPaths []PathLabel `json:"labeled_paths"`

	// DefaultLabels are applied to elements not matched by any path
	// If nil, unmatched elements inherit the resource-level labels
	DefaultLabels *PathLabelEntry `json:"default_labels,omitempty"`

	// ItemsPath specifies where the collection items are located (e.g., "/items", "" for root array)
	// This helps the gateway understand the structure for filtering
	ItemsPath string `json:"items_path,omitempty"`
}

PathLabels represents a collection of labeled paths in a JSON response. Guards return this structure to indicate which elements in the response have specific DIFC labels, without copying the data itself.

Example guard response:

{
  "labeled_paths": [
    { "path": "/items/0", "labels": { "secrecy": ["public"], "integrity": ["untrusted"] } },
    { "path": "/items/1", "labels": { "secrecy": ["repo_private"], "integrity": ["github_verified"] } }
  ],
  "default_labels": { "secrecy": ["public"], "integrity": ["untrusted"] }
}

func ParsePathLabels added in v0.1.10

func ParsePathLabels(data []byte) (*PathLabels, error)

ParsePathLabels parses a JSON response from a guard into PathLabels

type Resource

type Resource struct {
	Description string
	Secrecy     SecrecyLabel
	Integrity   IntegrityLabel
}

Resource represents an external system with label requirements (deprecated - use LabeledResource)

func EmptyResource

func EmptyResource() *Resource

Empty returns a resource with no label requirements

func NewResource

func NewResource(description string) *Resource

NewResource creates a new resource with the given description

type ResourceStructure

type ResourceStructure struct {
	// Fields maps field names/paths to their labels
	// For collections, use "items[*]" to indicate per-item labeling
	Fields map[string]*FieldLabels
}

ResourceStructure defines fine-grained labels for nested data structures

type SecrecyLabel

type SecrecyLabel struct {
	Label *Label
}

SecrecyLabel wraps Label with secrecy-specific flow semantics Secrecy flow: data can only flow to contexts with equal or more secrecy tags l ⊆ target (this has no tags that target doesn't have)

func NewSecrecyLabel

func NewSecrecyLabel() *SecrecyLabel

NewSecrecyLabel creates a new empty secrecy label

func NewSecrecyLabelWithTags

func NewSecrecyLabelWithTags(tags []Tag) *SecrecyLabel

NewSecrecyLabelWithTags creates a secrecy label with the given tags

func (*SecrecyLabel) CanFlowTo

func (l *SecrecyLabel) CanFlowTo(target *SecrecyLabel) bool

CanFlowTo checks if this secrecy label can flow to target Secrecy semantics: l ⊆ target (this has no tags that target doesn't have) Data can only flow to contexts with equal or more secrecy tags

func (*SecrecyLabel) CheckFlow

func (l *SecrecyLabel) CheckFlow(target *SecrecyLabel) (bool, []Tag)

CheckFlow checks if this secrecy label can flow to target and returns violation details if not

func (*SecrecyLabel) Clone

func (l *SecrecyLabel) Clone() *SecrecyLabel

Clone creates a copy of the secrecy label

type SimpleLabeledData

type SimpleLabeledData struct {
	Data   interface{}
	Labels *LabeledResource
}

SimpleLabeledData represents a single piece of data with uniform labels

func (*SimpleLabeledData) Overall

func (s *SimpleLabeledData) Overall() *LabeledResource

func (*SimpleLabeledData) ToResult

func (s *SimpleLabeledData) ToResult() (interface{}, error)

type Tag

type Tag string

Tag represents a single DIFC tag (e.g., "repo:owner/name", "agent:demo-agent")

type ViolationError

type ViolationError struct {
	Type         ViolationType
	Resource     string // Resource description
	IsWrite      bool   // true for write, false for read
	MissingTags  []Tag  // Tags the agent needs but doesn't have
	ExtraTags    []Tag  // Tags the agent has but shouldn't
	AgentTags    []Tag  // All agent tags (for context)
	ResourceTags []Tag  // All resource tags (for context)
}

ViolationError provides detailed information about a DIFC (Decentralized Information Flow Control) violation. It describes what kind of violation occurred, which resource was involved, and what needs to be done to resolve the violation.

This error type implements the error interface and provides human-readable error messages that explain the violation and suggest remediation steps. DIFC violations occur when:

  • Secrecy: An agent tries to access a resource but has secrecy tags that would leak sensitive information
  • Integrity: An agent tries to write to a resource but lacks the required integrity tags to ensure trustworthiness

Fields:

  • Type: The kind of violation (SecrecyViolation or IntegrityViolation)
  • Resource: Human-readable description of the resource being accessed
  • IsWrite: true for write operations, false for read operations
  • MissingTags: Tags the agent needs but doesn't have (for integrity violations)
  • ExtraTags: Tags the agent has but shouldn't (for secrecy violations)
  • AgentTags: Complete set of the agent's tags (for context)
  • ResourceTags: Complete set of the resource's tags (for context)

func (*ViolationError) Detailed

func (e *ViolationError) Detailed() string

Detailed returns a detailed error message with full context

func (*ViolationError) Error

func (e *ViolationError) Error() string

type ViolationType

type ViolationType string

ViolationType indicates what kind of DIFC violation occurred

const (
	SecrecyViolation   ViolationType = "secrecy"
	IntegrityViolation ViolationType = "integrity"
)

Jump to

Keyboard shortcuts

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