chore: add copyright headers, CI tests, and sanitize gitignore

This commit is contained in:
DmitrL-dev 2026-03-31 22:13:34 +10:00
parent 5cbb3d89d3
commit d1f844235e
325 changed files with 2267 additions and 902 deletions

View file

@ -1,3 +1,7 @@
// Copyright 2026 Syntrex Lab. All rights reserved.
// Use of this source code is governed by an Apache-2.0 license
// that can be found in the LICENSE file.
package shadow_ai
import (
@ -14,10 +18,10 @@ import (
type ApprovalStatus string
const (
ApprovalPending ApprovalStatus = "pending"
ApprovalApproved ApprovalStatus = "approved"
ApprovalDenied ApprovalStatus = "denied"
ApprovalExpired ApprovalStatus = "expired"
ApprovalPending ApprovalStatus = "pending"
ApprovalApproved ApprovalStatus = "approved"
ApprovalDenied ApprovalStatus = "denied"
ApprovalExpired ApprovalStatus = "expired"
ApprovalAutoApproved ApprovalStatus = "auto_approved"
)

View file

@ -1,3 +1,7 @@
// Copyright 2026 Syntrex Lab. All rights reserved.
// Use of this source code is governed by an Apache-2.0 license
// that can be found in the LICENSE file.
package shadow_ai
import (

View file

@ -1,3 +1,7 @@
// Copyright 2026 Syntrex Lab. All rights reserved.
// Use of this source code is governed by an Apache-2.0 license
// that can be found in the LICENSE file.
package shadow_ai
import (
@ -14,11 +18,11 @@ import (
// AISignatureDB contains known AI service signatures for detection.
type AISignatureDB struct {
mu sync.RWMutex
services []AIServiceInfo
domainPatterns []*domainPattern
apiKeyPatterns []*APIKeyPattern
httpSignatures []string
mu sync.RWMutex
services []AIServiceInfo
domainPatterns []*domainPattern
apiKeyPatterns []*APIKeyPattern
httpSignatures []string
}
type domainPattern struct {
@ -62,14 +66,14 @@ func (db *AISignatureDB) loadDefaults() {
// HTTP header signatures.
db.httpSignatures = []string{
"authorization: bearer sk-", // OpenAI
"authorization: bearer ant-", // Anthropic
"x-api-key: sk-ant-", // Anthropic v2
"x-goog-api-key:", // Google AI
"authorization: bearer gsk_", // Groq
"authorization: bearer hf_", // HuggingFace
"api-key:", // Azure OpenAI (x-ms header)
"x-api-key: xai-", // xAI Grok API
"authorization: bearer sk-", // OpenAI
"authorization: bearer ant-", // Anthropic
"x-api-key: sk-ant-", // Anthropic v2
"x-goog-api-key:", // Google AI
"authorization: bearer gsk_", // Groq
"authorization: bearer hf_", // HuggingFace
"api-key:", // Azure OpenAI (x-ms header)
"x-api-key: xai-", // xAI Grok API
}
}
@ -246,7 +250,7 @@ func (nd *NetworkDetector) SignatureDB() *AISignatureDB {
// UserBehaviorProfile tracks a user's AI access behavior for anomaly detection.
type UserBehaviorProfile struct {
UserID string `json:"user_id"`
AccessFrequency float64 `json:"access_frequency"` // Requests per hour
AccessFrequency float64 `json:"access_frequency"` // Requests per hour
DataVolumePerHour float64 `json:"data_volume_per_hour"` // Bytes per hour
KnownDestinations []string `json:"known_destinations"`
UpdatedAt time.Time `json:"updated_at"`

View file

@ -1,3 +1,7 @@
// Copyright 2026 Syntrex Lab. All rights reserved.
// Use of this source code is governed by an Apache-2.0 license
// that can be found in the LICENSE file.
package shadow_ai
import (
@ -17,62 +21,62 @@ import (
type DocReviewStatus string
const (
DocReviewPending DocReviewStatus = "pending"
DocReviewScanning DocReviewStatus = "scanning"
DocReviewClean DocReviewStatus = "clean"
DocReviewRedacted DocReviewStatus = "redacted"
DocReviewBlocked DocReviewStatus = "blocked"
DocReviewApproved DocReviewStatus = "approved"
DocReviewPending DocReviewStatus = "pending"
DocReviewScanning DocReviewStatus = "scanning"
DocReviewClean DocReviewStatus = "clean"
DocReviewRedacted DocReviewStatus = "redacted"
DocReviewBlocked DocReviewStatus = "blocked"
DocReviewApproved DocReviewStatus = "approved"
)
// ScanResult contains the results of scanning a document.
type ScanResult struct {
DocumentID string `json:"document_id"`
Status DocReviewStatus `json:"status"`
PIIFound []PIIMatch `json:"pii_found,omitempty"`
SecretsFound []SecretMatch `json:"secrets_found,omitempty"`
DataClass DataClassification `json:"data_classification"`
ContentHash string `json:"content_hash"`
ScannedAt time.Time `json:"scanned_at"`
SizeBytes int `json:"size_bytes"`
DocumentID string `json:"document_id"`
Status DocReviewStatus `json:"status"`
PIIFound []PIIMatch `json:"pii_found,omitempty"`
SecretsFound []SecretMatch `json:"secrets_found,omitempty"`
DataClass DataClassification `json:"data_classification"`
ContentHash string `json:"content_hash"`
ScannedAt time.Time `json:"scanned_at"`
SizeBytes int `json:"size_bytes"`
}
// PIIMatch represents a detected PII pattern in content.
type PIIMatch struct {
Type string `json:"type"` // "email", "phone", "ssn", "credit_card", "passport"
Location int `json:"location"` // Character offset
Type string `json:"type"` // "email", "phone", "ssn", "credit_card", "passport"
Location int `json:"location"` // Character offset
Length int `json:"length"`
Masked string `json:"masked"` // Redacted value, e.g., "j***@example.com"
Masked string `json:"masked"` // Redacted value, e.g., "j***@example.com"
}
// SecretMatch represents a detected secret/API key in content.
type SecretMatch struct {
Type string `json:"type"` // "api_key", "password", "token", "private_key"
Type string `json:"type"` // "api_key", "password", "token", "private_key"
Location int `json:"location"`
Length int `json:"length"`
Provider string `json:"provider"` // "OpenAI", "AWS", "GitHub", etc.
Provider string `json:"provider"` // "OpenAI", "AWS", "GitHub", etc.
}
// DocBridge manages document scanning, redaction, and review workflow.
type DocBridge struct {
mu sync.RWMutex
reviews map[string]*ScanResult
piiPatterns []*piiPattern
secretPats []secretPattern // Cached compiled patterns
signatures *AISignatureDB // Reused across scans
maxDocSize int // bytes
mu sync.RWMutex
reviews map[string]*ScanResult
piiPatterns []*piiPattern
secretPats []secretPattern // Cached compiled patterns
signatures *AISignatureDB // Reused across scans
maxDocSize int // bytes
}
type piiPattern struct {
name string
regex *regexp.Regexp
maskFn func(string) string
name string
regex *regexp.Regexp
maskFn func(string) string
}
// NewDocBridge creates a new Document Review Bridge.
func NewDocBridge() *DocBridge {
return &DocBridge{
reviews: make(map[string]*ScanResult),
reviews: make(map[string]*ScanResult),
piiPatterns: defaultPIIPatterns(),
secretPats: secretPatterns(),
signatures: NewAISignatureDB(),

View file

@ -1,3 +1,7 @@
// Copyright 2026 Syntrex Lab. All rights reserved.
// Use of this source code is governed by an Apache-2.0 license
// that can be found in the LICENSE file.
package shadow_ai
import (
@ -134,7 +138,7 @@ func (fm *FallbackManager) logDetectOnly(target, reason string) {
DetectionMethod: DetectNetwork,
Action: "detect_only",
Metadata: map[string]string{
"reason": reason,
"reason": reason,
"fallback_strategy": fm.strategy,
},
Timestamp: time.Now(),

View file

@ -1,3 +1,7 @@
// Copyright 2026 Syntrex Lab. All rights reserved.
// Use of this source code is governed by an Apache-2.0 license
// that can be found in the LICENSE file.
package shadow_ai
import (
@ -19,13 +23,13 @@ const (
// PluginHealth tracks the health state of a single plugin.
type PluginHealth struct {
Vendor string `json:"vendor"`
Type PluginType `json:"type"`
Status PluginStatus `json:"status"`
LastCheck time.Time `json:"last_check"`
Consecutive int `json:"consecutive_failures"`
Vendor string `json:"vendor"`
Type PluginType `json:"type"`
Status PluginStatus `json:"status"`
LastCheck time.Time `json:"last_check"`
Consecutive int `json:"consecutive_failures"`
Latency time.Duration `json:"latency"`
LastError string `json:"last_error,omitempty"`
LastError string `json:"last_error,omitempty"`
}
// MaxConsecutivePluginFailures before marking offline.

View file

@ -1,3 +1,7 @@
// Copyright 2026 Syntrex Lab. All rights reserved.
// Use of this source code is governed by an Apache-2.0 license
// that can be found in the LICENSE file.
// Package shadow_ai implements the Sentinel Shadow AI Control Module.
//
// Five levels of shadow AI management:
@ -107,7 +111,7 @@ type PluginConfig struct {
// IntegrationConfig is the top-level Shadow AI configuration.
type IntegrationConfig struct {
Plugins []PluginConfig `yaml:"plugins" json:"plugins"`
FallbackStrategy string `yaml:"fallback_strategy" json:"fallback_strategy"` // "detect_only" | "alert_only"
FallbackStrategy string `yaml:"fallback_strategy" json:"fallback_strategy"` // "detect_only" | "alert_only"
HealthCheckInterval time.Duration `yaml:"health_check_interval" json:"health_check_interval"` // default: 30s
}
@ -117,13 +121,13 @@ type IntegrationConfig struct {
type DetectionMethod string
const (
DetectNetwork DetectionMethod = "network" // Domain/IP match
DetectHTTP DetectionMethod = "http" // HTTP header signature
DetectTLS DetectionMethod = "tls" // TLS/JA3 fingerprint
DetectProcess DetectionMethod = "process" // AI tool process execution
DetectAPIKey DetectionMethod = "api_key" // AI API key in payload
DetectBehavioral DetectionMethod = "behavioral" // Anomalous AI access pattern
DetectClipboard DetectionMethod = "clipboard" // Large clipboard → AI browser pattern
DetectNetwork DetectionMethod = "network" // Domain/IP match
DetectHTTP DetectionMethod = "http" // HTTP header signature
DetectTLS DetectionMethod = "tls" // TLS/JA3 fingerprint
DetectProcess DetectionMethod = "process" // AI tool process execution
DetectAPIKey DetectionMethod = "api_key" // AI API key in payload
DetectBehavioral DetectionMethod = "behavioral" // Anomalous AI access pattern
DetectClipboard DetectionMethod = "clipboard" // Large clipboard → AI browser pattern
)
// DataClassification determines the approval tier required.
@ -141,22 +145,22 @@ type ShadowAIEvent struct {
ID string `json:"id"`
UserID string `json:"user_id"`
Hostname string `json:"hostname"`
Destination string `json:"destination"` // Target AI service domain/IP
AIService string `json:"ai_service"` // "chatgpt", "claude", "gemini", etc.
Destination string `json:"destination"` // Target AI service domain/IP
AIService string `json:"ai_service"` // "chatgpt", "claude", "gemini", etc.
DetectionMethod DetectionMethod `json:"detection_method"`
Action string `json:"action"` // "blocked", "allowed", "pending"
EnforcedBy string `json:"enforced_by"` // Plugin vendor that enforced
DataSize int64 `json:"data_size"` // Bytes sent to AI
Action string `json:"action"` // "blocked", "allowed", "pending"
EnforcedBy string `json:"enforced_by"` // Plugin vendor that enforced
DataSize int64 `json:"data_size"` // Bytes sent to AI
Timestamp time.Time `json:"timestamp"`
Metadata map[string]string `json:"metadata,omitempty"`
}
// AIServiceInfo describes a known AI service for signature matching.
type AIServiceInfo struct {
Name string `json:"name"` // "ChatGPT", "Claude", "Gemini"
Vendor string `json:"vendor"` // "OpenAI", "Anthropic", "Google"
Domains []string `json:"domains"` // ["*.openai.com", "chat.openai.com"]
Category string `json:"category"` // "llm", "image_gen", "code_assist"
Name string `json:"name"` // "ChatGPT", "Claude", "Gemini"
Vendor string `json:"vendor"` // "OpenAI", "Anthropic", "Google"
Domains []string `json:"domains"` // ["*.openai.com", "chat.openai.com"]
Category string `json:"category"` // "llm", "image_gen", "code_assist"
}
// BlockRequest is an API request to manually block a target.
@ -188,27 +192,27 @@ type Violator struct {
// ApprovalTier defines the approval requirements for a data classification level.
type ApprovalTier struct {
Name string `yaml:"name" json:"name"`
Name string `yaml:"name" json:"name"`
DataClass DataClassification `yaml:"data_class" json:"data_class"`
ApprovalNeeded []string `yaml:"approval_needed" json:"approval_needed"` // ["manager"], ["manager", "soc"], ["ciso"]
SLA time.Duration `yaml:"sla" json:"sla"`
AutoApprove bool `yaml:"auto_approve" json:"auto_approve"`
ApprovalNeeded []string `yaml:"approval_needed" json:"approval_needed"` // ["manager"], ["manager", "soc"], ["ciso"]
SLA time.Duration `yaml:"sla" json:"sla"`
AutoApprove bool `yaml:"auto_approve" json:"auto_approve"`
}
// ApprovalRequest tracks a pending approval for AI access.
type ApprovalRequest struct {
ID string `json:"id"`
DocID string `json:"doc_id"`
UserID string `json:"user_id"`
Tier string `json:"tier"`
DataClass DataClassification `json:"data_class"`
Status string `json:"status"` // "pending", "approved", "denied", "expired"
ApprovedBy string `json:"approved_by,omitempty"`
DeniedBy string `json:"denied_by,omitempty"`
Reason string `json:"reason,omitempty"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at"`
ResolvedAt time.Time `json:"resolved_at,omitempty"`
ID string `json:"id"`
DocID string `json:"doc_id"`
UserID string `json:"user_id"`
Tier string `json:"tier"`
DataClass DataClassification `json:"data_class"`
Status string `json:"status"` // "pending", "approved", "denied", "expired"
ApprovedBy string `json:"approved_by,omitempty"`
DeniedBy string `json:"denied_by,omitempty"`
Reason string `json:"reason,omitempty"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at"`
ResolvedAt time.Time `json:"resolved_at,omitempty"`
}
// ComplianceReport is the Shadow AI compliance report for GDPR/SOC2/EU AI Act.

View file

@ -1,3 +1,7 @@
// Copyright 2026 Syntrex Lab. All rights reserved.
// Use of this source code is governed by an Apache-2.0 license
// that can be found in the LICENSE file.
package shadow_ai
import (
@ -14,9 +18,9 @@ import (
// CheckPointEnforcer is a stub implementation for Check Point firewalls.
type CheckPointEnforcer struct {
apiURL string
apiKey string
logger *slog.Logger
apiURL string
apiKey string
logger *slog.Logger
}
func NewCheckPointEnforcer() *CheckPointEnforcer {

View file

@ -1,3 +1,7 @@
// Copyright 2026 Syntrex Lab. All rights reserved.
// Use of this source code is governed by an Apache-2.0 license
// that can be found in the LICENSE file.
package shadow_ai
import (
@ -13,10 +17,10 @@ type PluginFactory func() interface{}
// Thread-safe via sync.RWMutex.
type PluginRegistry struct {
mu sync.RWMutex
plugins map[string]interface{} // vendor → plugin instance
factories map[string]PluginFactory // "type_vendor" → factory
configs map[string]*PluginConfig // vendor → config
health map[string]*PluginHealth // vendor → health status
plugins map[string]interface{} // vendor → plugin instance
factories map[string]PluginFactory // "type_vendor" → factory
configs map[string]*PluginConfig // vendor → config
health map[string]*PluginHealth // vendor → health status
logger *slog.Logger
}

View file

@ -1,3 +1,7 @@
// Copyright 2026 Syntrex Lab. All rights reserved.
// Use of this source code is governed by an Apache-2.0 license
// that can be found in the LICENSE file.
package shadow_ai
import (
@ -36,7 +40,7 @@ func (m *mockFirewall) BlockDomain(_ context.Context, domain string, _ string) e
return nil
}
func (m *mockFirewall) UnblockIP(_ context.Context, _ string) error { return nil }
func (m *mockFirewall) UnblockIP(_ context.Context, _ string) error { return nil }
func (m *mockFirewall) UnblockDomain(_ context.Context, _ string) error { return nil }
func (m *mockFirewall) HealthCheck(_ context.Context) error {
@ -61,8 +65,8 @@ func (m *mockEDR) IsolateHost(_ context.Context, hostname string) error {
m.isolated = append(m.isolated, hostname)
return nil
}
func (m *mockEDR) ReleaseHost(_ context.Context, _ string) error { return nil }
func (m *mockEDR) KillProcess(_ context.Context, _ string, _ int) error { return nil }
func (m *mockEDR) ReleaseHost(_ context.Context, _ string) error { return nil }
func (m *mockEDR) KillProcess(_ context.Context, _ string, _ int) error { return nil }
func (m *mockEDR) QuarantineFile(_ context.Context, _ string, _ string) error { return nil }
func (m *mockEDR) HealthCheck(_ context.Context) error {
@ -87,8 +91,8 @@ func (m *mockGateway) BlockURL(_ context.Context, url string, _ string) error {
m.blockedURLs = append(m.blockedURLs, url)
return nil
}
func (m *mockGateway) UnblockURL(_ context.Context, _ string) error { return nil }
func (m *mockGateway) BlockCategory(_ context.Context, _ string) error { return nil }
func (m *mockGateway) UnblockURL(_ context.Context, _ string) error { return nil }
func (m *mockGateway) BlockCategory(_ context.Context, _ string) error { return nil }
func (m *mockGateway) HealthCheck(_ context.Context) error {
if !m.healthy {
@ -1075,8 +1079,8 @@ func TestApproval_ExpireOverdue(t *testing.T) {
func TestApproval_Stats(t *testing.T) {
ae := NewApprovalEngine()
ae.SubmitRequest("u1", "d1", DataPublic) // auto
ae.SubmitRequest("u2", "d2", DataInternal) // pending
ae.SubmitRequest("u1", "d1", DataPublic) // auto
ae.SubmitRequest("u2", "d2", DataInternal) // pending
req := ae.SubmitRequest("u3", "d3", DataConfidential) // pending
_ = ae.Deny(req.ID, "ciso", "no")
@ -1222,4 +1226,3 @@ func TestController_ReviewDocument_WithSecrets(t *testing.T) {
t.Fatal("blocked docs should not create approval")
}
}

View file

@ -1,3 +1,7 @@
// Copyright 2026 Syntrex Lab. All rights reserved.
// Use of this source code is governed by an Apache-2.0 license
// that can be found in the LICENSE file.
package shadow_ai
import (
@ -19,7 +23,7 @@ type ShadowAIController struct {
behavioral *BehavioralDetector
docBridge *DocBridge
approval *ApprovalEngine
events []ShadowAIEvent // In-memory event store (bounded)
events []ShadowAIEvent // In-memory event store (bounded)
maxEvents int
socEventFn func(source, severity, category, description string, meta map[string]string) // Bridge to SOC event bus
logger *slog.Logger