ccsignals

package
v0.0.0-...-74bcc06 Latest Latest
Warning

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

Go to latest
Published: Jan 21, 2026 License: AGPL-3.0 Imports: 11 Imported by: 0

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

View Source
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
)
View Source
const (
	HashBits           = 64
	DefaultShingleSize = 3
)

Variables

View Source
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

func LevenshteinDistance(s1, s2 string) int

LevenshteinDistance calculates the edit distance between two strings

func NormalizedEditDistance

func NormalizedEditDistance(s1, s2 string) float64

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
)

func (CCSignal) AllowsAI

func (s CCSignal) AllowsAI() bool

returns true if this signal permits AI usage empty/missing signal defaults to no-ai (restrictive default)

func (CCSignal) IsValid

func (s CCSignal) IsValid() bool

returns true if the signal is a valid CC Signal value

type Config

type Config struct {
	PasteDeltaThreshold int
	PasteLineThreshold  int
	UnlockThreshold     float64
	LockTTL             time.Duration
}

holds configuration for the detection system

func DefaultConfig

func DefaultConfig() Config

returns sensible defaults for the detection system

type ContentMatch

type ContentMatch struct {
	Found    bool
	OwnerID  string
	IsPublic bool
	CCSignal CCSignal
}

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

func (d *Detector) CheckUnlock(ctx context.Context, sessionID, currentCode string) error

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

func (d *Detector) IsLargeDelta(previousCode, newCode string) bool

determines if a code update has a large delta

func (*Detector) IsLocked

func (d *Detector) IsLocked(ctx context.Context, sessionID string) (bool, error)

checks if a session is currently paste-locked

func (*Detector) IsSignificantEdit

func (d *Detector) IsSignificantEdit(baseline, current string) bool

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

func (d *Detector) RemoveLock(ctx context.Context, sessionID string) error

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 Fingerprint

type Fingerprint uint64

represents a 64-bit SimHash fingerprint

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

func NewLSHIndex(numBands, similarityThreshold int) *LSHIndex

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)

func (*LSHIndex) Remove

func (idx *LSHIndex) Remove(id string)

removes a fingerprint record from the index

func (*LSHIndex) Size

func (idx *LSHIndex) Size() int

returns the number of records in the index

type LockState

type LockState struct {
	Locked       bool
	BaselineCode string
	LockedAt     time.Time
	Reason       string
}

represents the current lock state for a session

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) Close

func (s *MemoryLockStore) Close() error

stops the cleanup goroutine

func (*MemoryLockStore) GetLock

func (s *MemoryLockStore) GetLock(_ context.Context, sessionID string) (*LockState, error)

retrieves the current lock state for a session

func (*MemoryLockStore) RefreshTTL

func (s *MemoryLockStore) RefreshTTL(_ context.Context, sessionID string, ttl time.Duration) error

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

func (*MemoryLockStore) SetLock

func (s *MemoryLockStore) SetLock(_ context.Context, sessionID, baselineCode string, ttl time.Duration) error

sets a paste lock for a session with the baseline code

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) Close

func (s *RedisLockStore) Close() error

closes the redis connection

func (*RedisLockStore) GetLock

func (s *RedisLockStore) GetLock(ctx context.Context, sessionID string) (*LockState, error)

retrieves the current lock state for a session

func (*RedisLockStore) RefreshTTL

func (s *RedisLockStore) RefreshTTL(ctx context.Context, sessionID string, ttl time.Duration) error

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

func (*RedisLockStore) SetLock

func (s *RedisLockStore) SetLock(ctx context.Context, sessionID, baselineCode string, ttl time.Duration) error

sets a paste lock for a session with the baseline code

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

func NewSimHasher(shingleSize int) *SimHasher

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

Jump to

Keyboard shortcuts

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