Documentation
¶
Overview ¶
package ccsignals provides CC Signal enforcement for AI agents. detects paste operations and blocks AI requests on protected content until the user makes significant edits (demonstrating transformative use).
Index ¶
- Constants
- Variables
- func HammingDistance(a, b Fingerprint) int
- func IsSimilar(a, b Fingerprint, threshold int) bool
- func LevenshteinDistance(s1, s2 string) int
- func NormalizedEditDistance(s1, s2 string) float64
- type CCSignal
- type Config
- type ContentMatch
- type ContentValidator
- type DetectionResult
- type Detector
- func (d *Detector) CheckUnlock(ctx context.Context, sessionID, currentCode string) error
- func (d *Detector) DetectPaste(ctx context.Context, _, userID, previousCode, newCode string) (*DetectionResult, error)
- func (d *Detector) IsLargeDelta(previousCode, newCode string) bool
- func (d *Detector) IsLocked(ctx context.Context, sessionID string) (bool, error)
- func (d *Detector) IsSignificantEdit(baseline, current string) bool
- func (d *Detector) ProcessCodeUpdate(ctx context.Context, sessionID, userID, previousCode, newCode string) error
- func (d *Detector) RemoveLock(ctx context.Context, sessionID string) error
- func (d *Detector) SetLock(ctx context.Context, sessionID, baselineCode string, ttl time.Duration) error
- func (d *Detector) WithFingerprints(fps *IndexedFingerprintStore) *Detector
- type Fingerprint
- type FingerprintRecord
- type IndexedFingerprintStore
- func (s *IndexedFingerprintStore) AddFromStrudel(workID, creatorID string, ccSignal CCSignal, content string)
- func (s *IndexedFingerprintStore) FindBestMatch(content string) *MatchResult
- func (s *IndexedFingerprintStore) FindSimilar(content string) []*MatchResult
- func (s *IndexedFingerprintStore) InsertRecord(record *FingerprintRecord)
- func (s *IndexedFingerprintStore) Remove(workID string)
- func (s *IndexedFingerprintStore) Size() int
- func (s *IndexedFingerprintStore) UpdateFromStrudel(workID, creatorID string, ccSignal CCSignal, content string) bool
- type LSHIndex
- func (idx *LSHIndex) GetRecord(id string) *FingerprintRecord
- func (idx *LSHIndex) Insert(record *FingerprintRecord)
- func (idx *LSHIndex) Query(fingerprint Fingerprint) []*MatchResult
- func (idx *LSHIndex) QueryBest(fingerprint Fingerprint) *MatchResult
- func (idx *LSHIndex) Remove(id string)
- func (idx *LSHIndex) Size() int
- type LockState
- type LockStore
- type MatchResult
- type MemoryLockStore
- func (s *MemoryLockStore) Close() error
- func (s *MemoryLockStore) GetLock(_ context.Context, sessionID string) (*LockState, error)
- func (s *MemoryLockStore) RefreshTTL(_ context.Context, sessionID string, ttl time.Duration) error
- func (s *MemoryLockStore) RemoveLock(_ context.Context, sessionID string) error
- func (s *MemoryLockStore) SetLock(_ context.Context, sessionID, baselineCode string, ttl time.Duration) error
- type RedisLockStore
- func (s *RedisLockStore) Close() error
- func (s *RedisLockStore) GetLock(ctx context.Context, sessionID string) (*LockState, error)
- func (s *RedisLockStore) RefreshTTL(ctx context.Context, sessionID string, ttl time.Duration) error
- func (s *RedisLockStore) RemoveLock(ctx context.Context, sessionID string) error
- func (s *RedisLockStore) SetLock(ctx context.Context, sessionID, baselineCode string, ttl time.Duration) error
- type SessionProvider
- type SimHasher
- type StrudelValidator
Constants ¶
const ( // 4 bands with 16 bits each = 64 bits total DefaultNumBands = 4 // 10 bits out of 64 = ~84% similarity DefaultSimilarityThreshold = 10 // minimum bands to avoid uint16 overflow (64/4 = 16 bits per band) MinNumBands = 4 )
const ( HashBits = 64 DefaultShingleSize = 3 )
Variables ¶
var (
ErrNilStore = errors.New("ccsignals: store is nil")
)
Functions ¶
func HammingDistance ¶
func HammingDistance(a, b Fingerprint) int
calculates the number of differing bits between two fingerprints
func IsSimilar ¶
func IsSimilar(a, b Fingerprint, threshold int) bool
checks if two fingerprints are similar within the given threshold
func LevenshteinDistance ¶
LevenshteinDistance calculates the edit distance between two strings
func NormalizedEditDistance ¶
NormalizedEditDistance returns the edit distance as a ratio (0.0 to 1.0+)
Types ¶
type CCSignal ¶
type CCSignal string
represents Creative Commons Signals for AI usage consent
const ( SignalCredit CCSignal = "cc-cr" // credit: allow AI use with attribution SignalDirect CCSignal = "cc-dc" // credit + direct: attribution + financial support SignalEcosystem CCSignal = "cc-ec" // credit + ecosystem: attribution + contribute to commons SignalOpen CCSignal = "cc-op" // credit + open: attribution + keep derivatives open SignalNoAI CCSignal = "no-ai" // no AI: explicitly opt-out of AI usage )
type Config ¶
type Config struct {
PasteDeltaThreshold int
PasteLineThreshold int
UnlockThreshold float64
LockTTL time.Duration
}
holds configuration for the detection system
type ContentMatch ¶
represents a match result from content validation
type ContentValidator ¶
type ContentValidator interface {
ValidateOwnership(ctx context.Context, userID, code string) (*ContentMatch, error)
ValidatePublicContent(ctx context.Context, code string) (*ContentMatch, error)
}
defines the interface for validating content ownership
type DetectionResult ¶
type DetectionResult struct {
ShouldLock bool
Reason string
MatchedContent *ContentMatch
FingerprintMatch *MatchResult
}
contains the result of paste detection
type Detector ¶
type Detector struct {
// contains filtered or unexported fields
}
handles paste detection and lock management
func NewDetector ¶
func NewDetector(config Config, store LockStore, validator ContentValidator) *Detector
creates a new detector with the given dependencies
func (*Detector) CheckUnlock ¶
checks if edits are significant enough to unlock a session
func (*Detector) DetectPaste ¶
func (d *Detector) DetectPaste(ctx context.Context, _, userID, previousCode, newCode string) (*DetectionResult, error)
analyzes a code update and determines if it should be locked
func (*Detector) IsLargeDelta ¶
determines if a code update has a large delta
func (*Detector) IsSignificantEdit ¶
determines if edits are significant enough to unlock
func (*Detector) ProcessCodeUpdate ¶
func (d *Detector) ProcessCodeUpdate(ctx context.Context, sessionID, userID, previousCode, newCode string) error
handles a code update event, managing locks as needed
func (*Detector) RemoveLock ¶
removes a paste lock for a session
func (*Detector) SetLock ¶
func (d *Detector) SetLock(ctx context.Context, sessionID, baselineCode string, ttl time.Duration) error
sets a paste lock for a session
func (*Detector) WithFingerprints ¶
func (d *Detector) WithFingerprints(fps *IndexedFingerprintStore) *Detector
enables fingerprint-based similarity detection
type FingerprintRecord ¶
type FingerprintRecord struct {
ID string
Fingerprint Fingerprint
WorkID string
CreatorID string
CCSignal CCSignal
Content string
ContentLength int
}
stores a fingerprint with its metadata
type IndexedFingerprintStore ¶
type IndexedFingerprintStore struct {
// contains filtered or unexported fields
}
in-memory indexed fingerprint store (no persistence, computed from strudels at startup)
func NewInMemoryIndexedStore ¶
func NewInMemoryIndexedStore(numBands, threshold, shingleSize int) *IndexedFingerprintStore
creates a new in-memory indexed store
func (*IndexedFingerprintStore) AddFromStrudel ¶
func (s *IndexedFingerprintStore) AddFromStrudel(workID, creatorID string, ccSignal CCSignal, content string)
adds a fingerprint record computed from a strudel
func (*IndexedFingerprintStore) FindBestMatch ¶
func (s *IndexedFingerprintStore) FindBestMatch(content string) *MatchResult
finds the most similar content
func (*IndexedFingerprintStore) FindSimilar ¶
func (s *IndexedFingerprintStore) FindSimilar(content string) []*MatchResult
searches for content similar to the query
func (*IndexedFingerprintStore) InsertRecord ¶
func (s *IndexedFingerprintStore) InsertRecord(record *FingerprintRecord)
inserts a pre-loaded record directly into the index
func (*IndexedFingerprintStore) Remove ¶
func (s *IndexedFingerprintStore) Remove(workID string)
removes a fingerprint by work ID
func (*IndexedFingerprintStore) Size ¶
func (s *IndexedFingerprintStore) Size() int
returns the number of indexed fingerprints
func (*IndexedFingerprintStore) UpdateFromStrudel ¶
func (s *IndexedFingerprintStore) UpdateFromStrudel(workID, creatorID string, ccSignal CCSignal, content string) bool
updates a fingerprint only if the content changed significantly (optimization for frequent autosaves). "significant" means at least one line added or removed - small edits don't meaningfully affect SimHash.
type LSHIndex ¶
type LSHIndex struct {
// contains filtered or unexported fields
}
provides locality-sensitive hashing for efficient similarity search. divides fingerprints into bands and uses band values as bucket keys, reducing average lookup from O(n) to O(candidates in shared buckets).
func NewLSHIndex ¶
creates a new LSH index with the given configuration
func (*LSHIndex) GetRecord ¶
func (idx *LSHIndex) GetRecord(id string) *FingerprintRecord
retrieves a record by ID
func (*LSHIndex) Insert ¶
func (idx *LSHIndex) Insert(record *FingerprintRecord)
adds a fingerprint record to the index
func (*LSHIndex) Query ¶
func (idx *LSHIndex) Query(fingerprint Fingerprint) []*MatchResult
finds all similar fingerprints within the similarity threshold
func (*LSHIndex) QueryBest ¶
func (idx *LSHIndex) QueryBest(fingerprint Fingerprint) *MatchResult
finds the best matching fingerprint (lowest hamming distance)
type LockStore ¶
type LockStore interface {
SetLock(ctx context.Context, sessionID, baselineCode string, ttl time.Duration) error
GetLock(ctx context.Context, sessionID string) (*LockState, error)
RemoveLock(ctx context.Context, sessionID string) error
RefreshTTL(ctx context.Context, sessionID string, ttl time.Duration) error
}
defines the interface for storing paste locks
type MatchResult ¶
type MatchResult struct {
Record *FingerprintRecord
Distance int
}
represents a fingerprint match
type MemoryLockStore ¶
type MemoryLockStore struct {
// contains filtered or unexported fields
}
MemoryLockStore implements LockStore using in-memory storage
func NewMemoryLockStore ¶
func NewMemoryLockStore() *MemoryLockStore
creates a new in-memory lock store
func (*MemoryLockStore) RefreshTTL ¶
extends the lock TTL without changing other state
func (*MemoryLockStore) RemoveLock ¶
func (s *MemoryLockStore) RemoveLock(_ context.Context, sessionID string) error
removes the paste lock for a session
type RedisLockStore ¶
type RedisLockStore struct {
// contains filtered or unexported fields
}
implements LockStore using Redis
func NewRedisLockStore ¶
func NewRedisLockStore(client *redis.Client) *RedisLockStore
creates a new Redis-backed lock store
func NewRedisLockStoreFromURL ¶
func NewRedisLockStoreFromURL(redisURL string) (*RedisLockStore, error)
creates a new Redis-backed lock store from a URL
func (*RedisLockStore) RefreshTTL ¶
extends the lock TTL without changing other state
func (*RedisLockStore) RemoveLock ¶
func (s *RedisLockStore) RemoveLock(ctx context.Context, sessionID string) error
removes the paste lock for a session
type SessionProvider ¶
type SessionProvider interface {
IsSessionActive(sessionID string) bool
GetSessionCode(ctx context.Context, sessionID string) (string, error)
}
defines the interface for session management
type SimHasher ¶
type SimHasher struct {
// contains filtered or unexported fields
}
generates SimHash fingerprints from text content
func NewSimHasher ¶
creates a new SimHasher with the given shingle size
func (*SimHasher) Hash ¶
func (s *SimHasher) Hash(content string) Fingerprint
generates a SimHash fingerprint from text content
type StrudelValidator ¶
type StrudelValidator struct {
// contains filtered or unexported fields
}
implements ContentValidator using Algopatterns's strudels repository
func NewStrudelValidator ¶
func NewStrudelValidator(repo *strudels.Repository) *StrudelValidator
creates a ContentValidator backed by the strudels repository
func (*StrudelValidator) ValidateOwnership ¶
func (v *StrudelValidator) ValidateOwnership(ctx context.Context, userID, code string) (*ContentMatch, error)
checks if the user owns a strudel with this exact code
func (*StrudelValidator) ValidatePublicContent ¶
func (v *StrudelValidator) ValidatePublicContent(ctx context.Context, code string) (*ContentMatch, error)
checks if code matches any public strudel