mirror of
https://github.com/syntrex-lab/gomcp.git
synced 2026-04-24 20:06:21 +02:00
chore: add copyright headers, CI tests, and sanitize gitignore
This commit is contained in:
parent
5cbb3d89d3
commit
d1f844235e
325 changed files with 2267 additions and 902 deletions
31
.github/workflows/test.yml
vendored
Normal file
31
.github/workflows/test.yml
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
name: Go Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main", "master" ]
|
||||
pull_request:
|
||||
branches: [ "main", "master" ]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.25.0'
|
||||
cache: true
|
||||
|
||||
- name: Build
|
||||
run: go build -v ./...
|
||||
|
||||
- name: Test
|
||||
run: go test -v ./...
|
||||
|
||||
- name: Vet & Lint
|
||||
run: |
|
||||
go vet ./...
|
||||
go install honnef.co/go/tools/cmd/staticcheck@latest
|
||||
staticcheck ./...
|
||||
35
.gitignore
vendored
Normal file
35
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Binaries
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
gomcp
|
||||
soc
|
||||
immune
|
||||
sidecar
|
||||
dist/
|
||||
|
||||
# Databases
|
||||
*.db
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
*.wal
|
||||
*.shm
|
||||
|
||||
# Logs & Secrets
|
||||
*.log
|
||||
.env
|
||||
*.key
|
||||
.decisions.log
|
||||
sentinel_leash
|
||||
.rlm/
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Vendor
|
||||
vendor/
|
||||
12
README.md
12
README.md
|
|
@ -1,18 +1,18 @@
|
|||
# GoMCP: Recursive Language Model Server
|
||||
# GoMCP: The Secure Memory Core for AI Agents
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
> **The only Open-Source RLM (Recursive Language Model) Memory Server with Mathematically Proven Safety.**
|
||||
> **"Единственный RLM-сервер памяти с математически доказанной безопасностью (Sentinel Lattice). Работает локально, масштабируется глобально."**
|
||||
|
||||
GoMCP is the enterprise core of the Syntrex AI SOC ecosystem. It is an extremely fast, secure, and persistent Model Context Protocol (MCP) server entirely written in Go. GoMCP gives Large Language Models a permanent, evolving memory and self-modifying context, transforming standard text agents into self-improving persistent intelligences.
|
||||
|
||||
## 🚀 Key Features
|
||||
- **Context Consciousness Crystal (C³):** Hierarchical memory layers (L0-L3) combined with SQLite-backed temporal caching.
|
||||
- **57+ Native MCP Tools:** Deeply integrated tools for agentic self-reflection, codebase navigation, and file editing.
|
||||
- **Sub-millisecond latency:** Engineered for speed and durability under enterprise loads.
|
||||
- **Secure by Default:** Zero-G execution environment and robust isolation from the main operating system logic. DoH shielding, uTLS protocols, and session resumption natively integrated.
|
||||
- 🛡️ **Sentinel Lattice Primitives:** (TSA, CAFL, GPS...)
|
||||
- ⚡ **Sub-millisecond latency:** Pure Go execution with optional Rust bindings
|
||||
- 🔌 **57+ Native MCP Tools:** Deeply integrated tools right out of the box
|
||||
- 💾 **Persistent Causal Graph Memory:** Hierarchical memory layers (L0-L3) backed by robust SQLite temporal caching
|
||||
|
||||
## ⚡ Quick Start
|
||||
|
||||
|
|
|
|||
22
add_headers.py
Normal file
22
add_headers.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import os
|
||||
import glob
|
||||
|
||||
HEADER = """// 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.
|
||||
|
||||
"""
|
||||
|
||||
def run():
|
||||
for filepath in glob.glob("**/*.go", recursive=True):
|
||||
if os.path.isfile(filepath):
|
||||
with open(filepath, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Skip if already has header
|
||||
if "Copyright 2026 Syntrex Lab" not in content:
|
||||
with open(filepath, 'w', encoding='utf-8') as f:
|
||||
f.write(HEADER + content)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
|
|
@ -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.
|
||||
|
||||
// GoMCP v2 — High-performance Go-native MCP server for the RLM Toolkit.
|
||||
// Provides hierarchical persistent memory, cognitive state management,
|
||||
// causal reasoning chains, and code crystal indexing.
|
||||
|
|
|
|||
|
|
@ -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 main provides the SENTINEL immune agent (SEC-002 eBPF Runtime Guard).
|
||||
//
|
||||
// The immune agent monitors SOC processes at the kernel level using eBPF
|
||||
|
|
|
|||
|
|
@ -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 main provides the Universal Sidecar CLI entry point (§5.5).
|
||||
//
|
||||
// Usage:
|
||||
|
|
|
|||
|
|
@ -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 main provides the SOC Correlate process (SEC-001 Process Isolation).
|
||||
//
|
||||
// Responsibility: Receives persisted events from soc-ingest via IPC,
|
||||
|
|
|
|||
|
|
@ -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 main provides the SOC Ingest process (SEC-001 Process Isolation).
|
||||
//
|
||||
// Responsibility: HTTP endpoint, authentication, secret scanner,
|
||||
|
|
|
|||
|
|
@ -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 main provides the SOC Respond process (SEC-001 Process Isolation).
|
||||
//
|
||||
// Responsibility: Receives incidents from soc-correlate via IPC,
|
||||
|
|
|
|||
|
|
@ -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 main provides the standalone SOC API server entry point.
|
||||
//
|
||||
// @title SYNTREX Sentinel SOC API
|
||||
|
|
@ -29,10 +33,10 @@ import (
|
|||
"syscall"
|
||||
|
||||
"github.com/syntrex-lab/gomcp/internal/application/soc"
|
||||
socdomain "github.com/syntrex-lab/gomcp/internal/domain/soc"
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/engines"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/auth"
|
||||
socdomain "github.com/syntrex-lab/gomcp/internal/domain/soc"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/audit"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/auth"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/email"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/logging"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/postgres"
|
||||
|
|
@ -274,4 +278,3 @@ func configureMemorySafety(logger *slog.Logger) {
|
|||
"sys_mib", m.Sys/1024/1024,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
// syntrex-proxy — transparent reverse proxy that scans LLM prompts.
|
||||
//
|
||||
// Usage:
|
||||
|
|
|
|||
|
|
@ -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 docs Code generated by swaggo/swag. DO NOT EDIT
|
||||
package docs
|
||||
|
||||
|
|
|
|||
|
|
@ -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 contextengine
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 contextengine
|
||||
|
||||
import (
|
||||
|
|
@ -5,9 +9,9 @@ import (
|
|||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
ctxdomain "github.com/syntrex-lab/gomcp/internal/domain/context"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
ctxdomain "github.com/syntrex-lab/gomcp/internal/domain/context"
|
||||
)
|
||||
|
||||
func TestLoadConfig_FileNotExists(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -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 contextengine implements the Proactive Context Engine.
|
||||
// It automatically injects relevant memory facts into every MCP tool response
|
||||
// via ToolHandlerMiddleware, so the LLM always has context without asking.
|
||||
|
|
|
|||
|
|
@ -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 contextengine
|
||||
|
||||
import (
|
||||
|
|
@ -10,9 +14,9 @@ import (
|
|||
"github.com/mark3labs/mcp-go/mcp"
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/memory"
|
||||
|
||||
ctxdomain "github.com/syntrex-lab/gomcp/internal/domain/context"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
ctxdomain "github.com/syntrex-lab/gomcp/internal/domain/context"
|
||||
)
|
||||
|
||||
// --- Mock FactProvider ---
|
||||
|
|
|
|||
|
|
@ -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 contextengine — processor.go
|
||||
// Processes unprocessed interaction log entries into session summary facts.
|
||||
// This closes the memory loop: tool calls → interaction log → summary facts → boot instructions.
|
||||
|
|
|
|||
|
|
@ -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 contextengine
|
||||
|
||||
import (
|
||||
|
|
@ -5,10 +9,10 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/memory"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/sqlite"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/memory"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/sqlite"
|
||||
)
|
||||
|
||||
// --- mock FactStore for processor tests ---
|
||||
|
|
|
|||
|
|
@ -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 contextengine
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 contextengine
|
||||
|
||||
import (
|
||||
|
|
@ -6,9 +10,9 @@ import (
|
|||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/memory"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/memory"
|
||||
)
|
||||
|
||||
// --- Mock FactStore for provider tests ---
|
||||
|
|
|
|||
|
|
@ -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 lifecycle manages graceful shutdown with auto-save of session state,
|
||||
// cache flush, and database closure.
|
||||
package lifecycle
|
||||
|
|
|
|||
|
|
@ -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 lifecycle
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 lifecycle
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 lifecycle
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 orchestrator
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 orchestrator
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 orchestrator implements the DIP Heartbeat Orchestrator.
|
||||
//
|
||||
// The orchestrator runs a background loop with 4 modules:
|
||||
|
|
@ -439,7 +443,7 @@ func (o *Orchestrator) stabilityCheck(ctx context.Context, result *HeartbeatResu
|
|||
if err := o.store.Add(ctx, recoveryMarker); err == nil {
|
||||
o.mu.Lock()
|
||||
o.lastApoptosisWritten = time.Now()
|
||||
o.mu.Unlock()
|
||||
o.mu.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 orchestrator
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 resilience
|
||||
|
||||
import (
|
||||
|
|
@ -10,24 +14,24 @@ import (
|
|||
|
||||
// BehaviorProfile captures the runtime behavior of a component.
|
||||
type BehaviorProfile struct {
|
||||
Goroutines int `json:"goroutines"`
|
||||
HeapAllocMB float64 `json:"heap_alloc_mb"`
|
||||
HeapObjectsK float64 `json:"heap_objects_k"`
|
||||
GCPauseMs float64 `json:"gc_pause_ms"`
|
||||
NumGC uint32 `json:"num_gc"`
|
||||
FileDescriptors int `json:"file_descriptors,omitempty"`
|
||||
CustomMetrics map[string]float64 `json:"custom_metrics,omitempty"`
|
||||
Goroutines int `json:"goroutines"`
|
||||
HeapAllocMB float64 `json:"heap_alloc_mb"`
|
||||
HeapObjectsK float64 `json:"heap_objects_k"`
|
||||
GCPauseMs float64 `json:"gc_pause_ms"`
|
||||
NumGC uint32 `json:"num_gc"`
|
||||
FileDescriptors int `json:"file_descriptors,omitempty"`
|
||||
CustomMetrics map[string]float64 `json:"custom_metrics,omitempty"`
|
||||
}
|
||||
|
||||
// BehavioralAlert is emitted when a behavioral anomaly is detected.
|
||||
type BehavioralAlert struct {
|
||||
Component string `json:"component"`
|
||||
AnomalyType string `json:"anomaly_type"` // goroutine_leak, memory_leak, gc_pressure, etc.
|
||||
Metric string `json:"metric"`
|
||||
Current float64 `json:"current"`
|
||||
Baseline float64 `json:"baseline"`
|
||||
ZScore float64 `json:"z_score"`
|
||||
Severity string `json:"severity"`
|
||||
Component string `json:"component"`
|
||||
AnomalyType string `json:"anomaly_type"` // goroutine_leak, memory_leak, gc_pressure, etc.
|
||||
Metric string `json:"metric"`
|
||||
Current float64 `json:"current"`
|
||||
Baseline float64 `json:"baseline"`
|
||||
ZScore float64 `json:"z_score"`
|
||||
Severity string `json:"severity"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
|
||||
|
|
@ -35,12 +39,12 @@ type BehavioralAlert struct {
|
|||
// It profiles the current process and compares against learned baselines.
|
||||
// On Linux, eBPF hooks (immune/resilience_hooks.c) extend this to kernel level.
|
||||
type BehavioralAnalyzer struct {
|
||||
mu sync.RWMutex
|
||||
metricsDB *MetricsDB
|
||||
alertBus chan BehavioralAlert
|
||||
interval time.Duration
|
||||
component string // self component name
|
||||
logger *slog.Logger
|
||||
mu sync.RWMutex
|
||||
metricsDB *MetricsDB
|
||||
alertBus chan BehavioralAlert
|
||||
interval time.Duration
|
||||
component string // self component name
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
// NewBehavioralAnalyzer creates a new behavioral analyzer.
|
||||
|
|
@ -112,10 +116,10 @@ func (ba *BehavioralAnalyzer) storeMetrics(p BehaviorProfile) {
|
|||
// detectAnomalies checks each metric against its baseline via Z-score.
|
||||
func (ba *BehavioralAnalyzer) detectAnomalies(p BehaviorProfile) {
|
||||
checks := []struct {
|
||||
metric string
|
||||
value float64
|
||||
metric string
|
||||
value float64
|
||||
anomalyType string
|
||||
severity string
|
||||
severity string
|
||||
}{
|
||||
{"goroutines", float64(p.Goroutines), "goroutine_leak", "WARNING"},
|
||||
{"heap_alloc_mb", p.HeapAllocMB, "memory_leak", "CRITICAL"},
|
||||
|
|
|
|||
|
|
@ -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 resilience
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 resilience
|
||||
|
||||
import (
|
||||
|
|
@ -66,10 +70,10 @@ type Action struct {
|
|||
|
||||
// TriggerCondition defines when a healing strategy activates.
|
||||
type TriggerCondition struct {
|
||||
Metrics []string `json:"metrics,omitempty"`
|
||||
Metrics []string `json:"metrics,omitempty"`
|
||||
Statuses []ComponentStatus `json:"statuses,omitempty"`
|
||||
ConsecutiveFailures int `json:"consecutive_failures"`
|
||||
WithinWindow time.Duration `json:"within_window"`
|
||||
ConsecutiveFailures int `json:"consecutive_failures"`
|
||||
WithinWindow time.Duration `json:"within_window"`
|
||||
}
|
||||
|
||||
// RollbackPlan defines what happens if healing fails.
|
||||
|
|
@ -91,11 +95,11 @@ type HealingStrategy struct {
|
|||
|
||||
// Diagnosis is the result of root cause analysis.
|
||||
type Diagnosis struct {
|
||||
Component string `json:"component"`
|
||||
Metric string `json:"metric"`
|
||||
RootCause string `json:"root_cause"`
|
||||
Confidence float64 `json:"confidence"`
|
||||
SuggestedFix string `json:"suggested_fix"`
|
||||
Component string `json:"component"`
|
||||
Metric string `json:"metric"`
|
||||
RootCause string `json:"root_cause"`
|
||||
Confidence float64 `json:"confidence"`
|
||||
SuggestedFix string `json:"suggested_fix"`
|
||||
RelatedAlerts []HealthAlert `json:"related_alerts,omitempty"`
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +121,7 @@ type HealingOperation struct {
|
|||
// ActionLog records the execution of a single action.
|
||||
type ActionLog struct {
|
||||
Action ActionType `json:"action"`
|
||||
StartedAt time.Time `json:"started_at"`
|
||||
StartedAt time.Time `json:"started_at"`
|
||||
Duration time.Duration `json:"duration"`
|
||||
Success bool `json:"success"`
|
||||
Error string `json:"error,omitempty"`
|
||||
|
|
|
|||
|
|
@ -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 resilience
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 resilience
|
||||
|
||||
import "time"
|
||||
|
|
|
|||
|
|
@ -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 resilience
|
||||
|
||||
import (
|
||||
|
|
@ -63,12 +67,12 @@ type ComponentConfig struct {
|
|||
|
||||
// ComponentHealth tracks the health state of a single component.
|
||||
type ComponentHealth struct {
|
||||
Name string `json:"name"`
|
||||
Status ComponentStatus `json:"status"`
|
||||
Name string `json:"name"`
|
||||
Status ComponentStatus `json:"status"`
|
||||
Metrics map[string]float64 `json:"metrics"`
|
||||
LastCheck time.Time `json:"last_check"`
|
||||
Consecutive int `json:"consecutive_failures"`
|
||||
Config ComponentConfig `json:"-"`
|
||||
LastCheck time.Time `json:"last_check"`
|
||||
Consecutive int `json:"consecutive_failures"`
|
||||
Config ComponentConfig `json:"-"`
|
||||
}
|
||||
|
||||
// HealthAlert represents a detected health anomaly.
|
||||
|
|
|
|||
|
|
@ -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 resilience
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 resilience
|
||||
|
||||
import (
|
||||
|
|
@ -23,11 +27,11 @@ const (
|
|||
|
||||
// IntegrityReport is the full result of an integrity verification.
|
||||
type IntegrityReport struct {
|
||||
Overall IntegrityStatus `json:"overall"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Binaries map[string]BinaryStatus `json:"binaries,omitempty"`
|
||||
Chain *ChainStatus `json:"chain,omitempty"`
|
||||
Configs map[string]ConfigStatus `json:"configs,omitempty"`
|
||||
Overall IntegrityStatus `json:"overall"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Binaries map[string]BinaryStatus `json:"binaries,omitempty"`
|
||||
Chain *ChainStatus `json:"chain,omitempty"`
|
||||
Configs map[string]ConfigStatus `json:"configs,omitempty"`
|
||||
}
|
||||
|
||||
// BinaryStatus is the integrity status of a single binary.
|
||||
|
|
@ -56,13 +60,13 @@ type ConfigStatus struct {
|
|||
// IntegrityVerifier performs periodic integrity checks on binaries,
|
||||
// decision chain, and config files.
|
||||
type IntegrityVerifier struct {
|
||||
mu sync.RWMutex
|
||||
binaryHashes map[string]string // path → expected SHA-256
|
||||
configPaths []string // config files to verify
|
||||
hmacKey []byte // key for config HMAC-SHA256
|
||||
chainPath string // path to decision chain log
|
||||
logger *slog.Logger
|
||||
lastReport *IntegrityReport
|
||||
mu sync.RWMutex
|
||||
binaryHashes map[string]string // path → expected SHA-256
|
||||
configPaths []string // config files to verify
|
||||
hmacKey []byte // key for config HMAC-SHA256
|
||||
chainPath string // path to decision chain log
|
||||
logger *slog.Logger
|
||||
lastReport *IntegrityReport
|
||||
}
|
||||
|
||||
// NewIntegrityVerifier creates a new integrity verifier.
|
||||
|
|
|
|||
|
|
@ -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 resilience implements the Sentinel Autonomous Resilience Layer (SARL).
|
||||
//
|
||||
// Five levels of autonomous self-recovery:
|
||||
|
|
|
|||
|
|
@ -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 resilience
|
||||
|
||||
import (
|
||||
|
|
@ -43,13 +47,13 @@ type ModeActionFunc func(mode EmergencyMode, action string, params map[string]in
|
|||
|
||||
// PreservationEngine manages emergency modes (safe/lockdown/apoptosis).
|
||||
type PreservationEngine struct {
|
||||
mu sync.RWMutex
|
||||
currentMode EmergencyMode
|
||||
activation *ModeActivation
|
||||
history []PreservationEvent
|
||||
actionFn ModeActionFunc
|
||||
integrityFn func() IntegrityReport // pluggable integrity check
|
||||
logger *slog.Logger
|
||||
mu sync.RWMutex
|
||||
currentMode EmergencyMode
|
||||
activation *ModeActivation
|
||||
history []PreservationEvent
|
||||
actionFn ModeActionFunc
|
||||
integrityFn func() IntegrityReport // pluggable integrity check
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
// NewPreservationEngine creates a new preservation engine.
|
||||
|
|
|
|||
|
|
@ -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 resilience
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 resilience
|
||||
|
||||
import (
|
||||
|
|
@ -12,58 +16,58 @@ import (
|
|||
type PlaybookStatus string
|
||||
|
||||
const (
|
||||
PlaybookPending PlaybookStatus = "PENDING"
|
||||
PlaybookRunning PlaybookStatus = "RUNNING"
|
||||
PlaybookSucceeded PlaybookStatus = "SUCCEEDED"
|
||||
PlaybookFailed PlaybookStatus = "FAILED"
|
||||
PlaybookPending PlaybookStatus = "PENDING"
|
||||
PlaybookRunning PlaybookStatus = "RUNNING"
|
||||
PlaybookSucceeded PlaybookStatus = "SUCCEEDED"
|
||||
PlaybookFailed PlaybookStatus = "FAILED"
|
||||
PlaybookRolledBack PlaybookStatus = "ROLLED_BACK"
|
||||
)
|
||||
|
||||
// PlaybookStep is a single step in a recovery playbook.
|
||||
type PlaybookStep struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"` // shell, api, consensus, crypto, systemd, http, prometheus
|
||||
Timeout time.Duration `json:"timeout"`
|
||||
Retries int `json:"retries"`
|
||||
Params map[string]interface{} `json:"params,omitempty"`
|
||||
OnError string `json:"on_error"` // abort, continue, rollback
|
||||
Condition string `json:"condition,omitempty"` // prerequisite condition
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"` // shell, api, consensus, crypto, systemd, http, prometheus
|
||||
Timeout time.Duration `json:"timeout"`
|
||||
Retries int `json:"retries"`
|
||||
Params map[string]interface{} `json:"params,omitempty"`
|
||||
OnError string `json:"on_error"` // abort, continue, rollback
|
||||
Condition string `json:"condition,omitempty"` // prerequisite condition
|
||||
}
|
||||
|
||||
// Playbook defines a complete recovery procedure.
|
||||
type Playbook struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
TriggerMetric string `json:"trigger_metric"`
|
||||
TriggerSeverity string `json:"trigger_severity"`
|
||||
DiagnosisChecks []PlaybookStep `json:"diagnosis_checks"`
|
||||
Actions []PlaybookStep `json:"actions"`
|
||||
RollbackActions []PlaybookStep `json:"rollback_actions"`
|
||||
SuccessCriteria []string `json:"success_criteria"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
TriggerMetric string `json:"trigger_metric"`
|
||||
TriggerSeverity string `json:"trigger_severity"`
|
||||
DiagnosisChecks []PlaybookStep `json:"diagnosis_checks"`
|
||||
Actions []PlaybookStep `json:"actions"`
|
||||
RollbackActions []PlaybookStep `json:"rollback_actions"`
|
||||
SuccessCriteria []string `json:"success_criteria"`
|
||||
}
|
||||
|
||||
// PlaybookExecution tracks a single playbook run.
|
||||
type PlaybookExecution struct {
|
||||
ID string `json:"id"`
|
||||
PlaybookID string `json:"playbook_id"`
|
||||
Component string `json:"component"`
|
||||
Status PlaybookStatus `json:"status"`
|
||||
StartedAt time.Time `json:"started_at"`
|
||||
CompletedAt time.Time `json:"completed_at,omitempty"`
|
||||
StepsRun []StepResult `json:"steps_run"`
|
||||
Error string `json:"error,omitempty"`
|
||||
ID string `json:"id"`
|
||||
PlaybookID string `json:"playbook_id"`
|
||||
Component string `json:"component"`
|
||||
Status PlaybookStatus `json:"status"`
|
||||
StartedAt time.Time `json:"started_at"`
|
||||
CompletedAt time.Time `json:"completed_at,omitempty"`
|
||||
StepsRun []StepResult `json:"steps_run"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// StepResult records the execution of a single playbook step.
|
||||
type StepResult struct {
|
||||
StepID string `json:"step_id"`
|
||||
StepName string `json:"step_name"`
|
||||
Success bool `json:"success"`
|
||||
Duration time.Duration `json:"duration"`
|
||||
Output string `json:"output,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
StepID string `json:"step_id"`
|
||||
StepName string `json:"step_name"`
|
||||
Success bool `json:"success"`
|
||||
Duration time.Duration `json:"duration"`
|
||||
Output string `json:"output,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// PlaybookExecutorFunc runs a single playbook step.
|
||||
|
|
|
|||
|
|
@ -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 resilience
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 resources provides MCP resource implementations.
|
||||
package resources
|
||||
|
||||
|
|
|
|||
|
|
@ -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 resources
|
||||
|
||||
import (
|
||||
|
|
@ -5,11 +9,11 @@ import (
|
|||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/memory"
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/session"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/sqlite"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func newTestProvider(t *testing.T) (*Provider, *sqlite.DB, *sqlite.DB) {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 sidecar
|
||||
|
||||
import (
|
||||
|
|
@ -42,15 +46,15 @@ func NewBusClient(baseURL, sensorID, apiKey string) *BusClient {
|
|||
// ingestPayload matches the SOC ingest API expected JSON.
|
||||
type ingestPayload struct {
|
||||
Source string `json:"source"`
|
||||
SensorID string `json:"sensor_id"`
|
||||
SensorKey string `json:"sensor_key,omitempty"`
|
||||
Severity string `json:"severity"`
|
||||
Category string `json:"category"`
|
||||
Subcategory string `json:"subcategory,omitempty"`
|
||||
Confidence float64 `json:"confidence"`
|
||||
Description string `json:"description"`
|
||||
SessionID string `json:"session_id,omitempty"`
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
SensorID string `json:"sensor_id"`
|
||||
SensorKey string `json:"sensor_key,omitempty"`
|
||||
Severity string `json:"severity"`
|
||||
Category string `json:"category"`
|
||||
Subcategory string `json:"subcategory,omitempty"`
|
||||
Confidence float64 `json:"confidence"`
|
||||
Description string `json:"description"`
|
||||
SessionID string `json:"session_id,omitempty"`
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
// SendEvent posts a SOCEvent to the Event Bus.
|
||||
|
|
@ -58,15 +62,15 @@ type ingestPayload struct {
|
|||
func (c *BusClient) SendEvent(ctx context.Context, evt *domsoc.SOCEvent) error {
|
||||
payload := ingestPayload{
|
||||
Source: string(evt.Source),
|
||||
SensorID: c.sensorID,
|
||||
SensorKey: c.apiKey,
|
||||
Severity: string(evt.Severity),
|
||||
Category: evt.Category,
|
||||
SensorID: c.sensorID,
|
||||
SensorKey: c.apiKey,
|
||||
Severity: string(evt.Severity),
|
||||
Category: evt.Category,
|
||||
Subcategory: evt.Subcategory,
|
||||
Confidence: evt.Confidence,
|
||||
Confidence: evt.Confidence,
|
||||
Description: evt.Description,
|
||||
SessionID: evt.SessionID,
|
||||
Metadata: evt.Metadata,
|
||||
SessionID: evt.SessionID,
|
||||
Metadata: evt.Metadata,
|
||||
}
|
||||
|
||||
body, err := json.Marshal(payload)
|
||||
|
|
|
|||
|
|
@ -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 sidecar implements the Universal Sidecar (§5.5) — a zero-dependency
|
||||
// Go binary that runs alongside SENTINEL sensors, tails their STDOUT/logs,
|
||||
// and pushes parsed security events to the SOC Event Bus.
|
||||
|
|
|
|||
|
|
@ -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 sidecar
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 sidecar
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 sidecar
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 soc provides SOC analytics: event trends, severity distribution,
|
||||
// top sources, MITRE ATT&CK coverage, and time-series aggregation.
|
||||
package soc
|
||||
|
|
|
|||
|
|
@ -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 soc
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 soc
|
||||
|
||||
import (
|
||||
|
|
@ -524,4 +528,3 @@ func TestE2E_CrescendoEscalation(t *testing.T) {
|
|||
assert.Equal(t, domsoc.SeverityCritical, lastInc.Severity)
|
||||
assert.Contains(t, lastInc.MITREMapping, "T1059")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 soc
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 soc
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 soc provides application services for the SENTINEL AI SOC subsystem.
|
||||
package soc
|
||||
|
||||
|
|
@ -29,14 +33,14 @@ const (
|
|||
// Service orchestrates the SOC event pipeline:
|
||||
// Step 0: Secret Scanner (INVARIANT) → DIP → Decision Logger → Persist → Correlation.
|
||||
type Service struct {
|
||||
mu sync.RWMutex
|
||||
repo domsoc.SOCRepository
|
||||
logger *audit.DecisionLogger
|
||||
rules []domsoc.SOCCorrelationRule
|
||||
mu sync.RWMutex
|
||||
repo domsoc.SOCRepository
|
||||
logger *audit.DecisionLogger
|
||||
rules []domsoc.SOCCorrelationRule
|
||||
playbookEngine *domsoc.PlaybookEngine
|
||||
executorRegistry *domsoc.ExecutorRegistry
|
||||
sensors map[string]*domsoc.Sensor
|
||||
draining bool // §15.7: graceful shutdown mode — rejects new events
|
||||
sensors map[string]*domsoc.Sensor
|
||||
draining bool // §15.7: graceful shutdown mode — rejects new events
|
||||
|
||||
// Alert Clustering engine (§7.6): groups related alerts.
|
||||
clusterEngine *domsoc.ClusterEngine
|
||||
|
|
@ -45,8 +49,8 @@ type Service struct {
|
|||
eventBus *domsoc.EventBus
|
||||
|
||||
// Rate limiting per sensor (§17.3): sensorID → timestamps of recent events.
|
||||
sensorRates map[string][]time.Time
|
||||
rateLimitDisabled bool
|
||||
sensorRates map[string][]time.Time
|
||||
rateLimitDisabled bool
|
||||
|
||||
// Sensor authentication (§17.3 T-01): sensorID → pre-shared key.
|
||||
sensorKeys map[string]string
|
||||
|
|
@ -85,9 +89,9 @@ func NewService(repo domsoc.SOCRepository, logger *audit.DecisionLogger) *Servic
|
|||
// Build executor registry with all SOAR action handlers
|
||||
reg := domsoc.NewExecutorRegistry()
|
||||
reg.Register(&domsoc.BlockIPExecutor{})
|
||||
reg.Register(domsoc.NewNotifyExecutor("")) // URL configured via SetNotifyURL()
|
||||
reg.Register(domsoc.NewNotifyExecutor("")) // URL configured via SetNotifyURL()
|
||||
reg.Register(domsoc.NewQuarantineExecutor())
|
||||
reg.Register(domsoc.NewEscalateExecutor("")) // URL configured via SetEscalateURL()
|
||||
reg.Register(domsoc.NewEscalateExecutor("")) // URL configured via SetEscalateURL()
|
||||
// Webhook executor configured separately via SetWebhookConfig()
|
||||
|
||||
// Create playbook engine with live executor handler (not just logging)
|
||||
|
|
@ -100,21 +104,21 @@ func NewService(repo domsoc.SOCRepository, logger *audit.DecisionLogger) *Servic
|
|||
)
|
||||
|
||||
return &Service{
|
||||
repo: repo,
|
||||
logger: logger,
|
||||
rules: domsoc.DefaultSOCCorrelationRules(),
|
||||
playbookEngine: pe,
|
||||
executorRegistry: reg,
|
||||
sensors: make(map[string]*domsoc.Sensor),
|
||||
clusterEngine: domsoc.NewClusterEngine(domsoc.DefaultClusterConfig()),
|
||||
eventBus: domsoc.NewEventBus(256),
|
||||
sensorRates: make(map[string][]time.Time),
|
||||
zeroG: domsoc.NewZeroGMode(),
|
||||
p2pSync: domsoc.NewP2PSyncService(),
|
||||
anomaly: domsoc.NewAnomalyDetector(),
|
||||
repo: repo,
|
||||
logger: logger,
|
||||
rules: domsoc.DefaultSOCCorrelationRules(),
|
||||
playbookEngine: pe,
|
||||
executorRegistry: reg,
|
||||
sensors: make(map[string]*domsoc.Sensor),
|
||||
clusterEngine: domsoc.NewClusterEngine(domsoc.DefaultClusterConfig()),
|
||||
eventBus: domsoc.NewEventBus(256),
|
||||
sensorRates: make(map[string][]time.Time),
|
||||
zeroG: domsoc.NewZeroGMode(),
|
||||
p2pSync: domsoc.NewP2PSyncService(),
|
||||
anomaly: domsoc.NewAnomalyDetector(),
|
||||
threatIntelEngine: domsoc.NewThreatIntelEngine(),
|
||||
retention: domsoc.NewDataRetentionPolicy(),
|
||||
scanSemaphore: make(chan struct{}, 8), // §20.1: max 8 concurrent scans
|
||||
retention: domsoc.NewDataRetentionPolicy(),
|
||||
scanSemaphore: make(chan struct{}, 8), // §20.1: max 8 concurrent scans
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -213,7 +217,6 @@ func (s *Service) TestWebhook() []WebhookResult {
|
|||
return wh.NotifyIncident("webhook_test", testIncident)
|
||||
}
|
||||
|
||||
|
||||
// Drain puts the service into drain mode (§15.7 Stage 1).
|
||||
// New events are rejected with ErrDraining; existing processing continues.
|
||||
func (s *Service) Drain() {
|
||||
|
|
@ -301,6 +304,7 @@ func (s *Service) runRetentionPurge() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IngestEvent processes an incoming security event through the SOC pipeline.
|
||||
// Returns the event ID and any incident created by correlation.
|
||||
//
|
||||
|
|
@ -768,9 +772,9 @@ func (s *Service) GetRecentDecisions(limit int) []map[string]any {
|
|||
return []map[string]any{
|
||||
{
|
||||
"total_decisions": s.logger.Count(),
|
||||
"hash_chain": s.logger.PrevHash(),
|
||||
"log_path": s.logger.Path(),
|
||||
"status": "operational",
|
||||
"hash_chain": s.logger.PrevHash(),
|
||||
"log_path": s.logger.Path(),
|
||||
"status": "operational",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -979,10 +983,10 @@ func (s *Service) ListIncidentsAdvanced(f IncidentFilter) (*IncidentFilterResult
|
|||
|
||||
// BulkAction defines a batch operation on incidents.
|
||||
type BulkAction struct {
|
||||
Action string `json:"action"` // assign, status, close, delete
|
||||
Action string `json:"action"` // assign, status, close, delete
|
||||
IncidentIDs []string `json:"incident_ids"`
|
||||
Value string `json:"value"` // analyst email, new status
|
||||
Actor string `json:"actor"` // who initiated
|
||||
Value string `json:"value"` // analyst email, new status
|
||||
Actor string `json:"actor"` // who initiated
|
||||
}
|
||||
|
||||
// BulkActionResult is the result of a batch operation.
|
||||
|
|
@ -1030,12 +1034,12 @@ type SLAThreshold struct {
|
|||
|
||||
// SLAStatus represents an incident's SLA compliance state.
|
||||
type SLAStatus struct {
|
||||
ResponseBreached bool `json:"response_breached"`
|
||||
ResolutionBreached bool `json:"resolution_breached"`
|
||||
ResponseRemaining float64 `json:"response_remaining_min"` // minutes remaining (negative = breached)
|
||||
ResponseBreached bool `json:"response_breached"`
|
||||
ResolutionBreached bool `json:"resolution_breached"`
|
||||
ResponseRemaining float64 `json:"response_remaining_min"` // minutes remaining (negative = breached)
|
||||
ResolutionRemaining float64 `json:"resolution_remaining_min"`
|
||||
ResponseTarget float64 `json:"response_target_min"`
|
||||
ResolutionTarget float64 `json:"resolution_target_min"`
|
||||
ResponseTarget float64 `json:"response_target_min"`
|
||||
ResolutionTarget float64 `json:"resolution_target_min"`
|
||||
}
|
||||
|
||||
// DefaultSLAThresholds returns SLA targets per severity.
|
||||
|
|
@ -1161,7 +1165,7 @@ func (s *Service) Dashboard(tenantID string) (*DashboardData, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
lastHourEvents, err := s.repo.CountEventsSince(tenantID, time.Now().Add(-1 * time.Hour))
|
||||
lastHourEvents, err := s.repo.CountEventsSince(tenantID, time.Now().Add(-1*time.Hour))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 soc
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 soc
|
||||
|
||||
import (
|
||||
|
|
@ -17,7 +21,7 @@ type STIXBundle struct {
|
|||
|
||||
// STIXObject represents a generic STIX 2.1 object.
|
||||
type STIXObject struct {
|
||||
Type string `json:"type"` // indicator, malware, attack-pattern, etc.
|
||||
Type string `json:"type"` // indicator, malware, attack-pattern, etc.
|
||||
ID string `json:"id"`
|
||||
Created time.Time `json:"created"`
|
||||
Modified time.Time `json:"modified"`
|
||||
|
|
|
|||
|
|
@ -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 soc
|
||||
|
||||
import (
|
||||
|
|
@ -111,8 +115,8 @@ func TestProcessBundle_FiltersNonIndicators(t *testing.T) {
|
|||
Objects: []STIXObject{
|
||||
{Type: "indicator", Pattern: "[ipv4-addr:value = '10.0.0.1']", Modified: time.Now()},
|
||||
{Type: "malware", Name: "BadMalware"}, // should be skipped
|
||||
{Type: "indicator", Pattern: ""}, // empty pattern → skipped
|
||||
{Type: "attack-pattern", Name: "Phish"}, // should be skipped
|
||||
{Type: "indicator", Pattern: ""}, // empty pattern → skipped
|
||||
{Type: "attack-pattern", Name: "Phish"}, // should be skipped
|
||||
{Type: "indicator", Pattern: "[domain-name:value = 'bad.com']", Modified: time.Now()},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 soc provides a threat intelligence feed integration
|
||||
// for enriching SOC events and correlation rules.
|
||||
//
|
||||
|
|
@ -36,9 +40,9 @@ const (
|
|||
type IOC struct {
|
||||
Type IOCType `json:"type"`
|
||||
Value string `json:"value"`
|
||||
Source string `json:"source"` // Feed name
|
||||
Severity string `json:"severity"` // critical/high/medium/low
|
||||
Tags []string `json:"tags"` // MITRE ATT&CK, campaign, etc.
|
||||
Source string `json:"source"` // Feed name
|
||||
Severity string `json:"severity"` // critical/high/medium/low
|
||||
Tags []string `json:"tags"` // MITRE ATT&CK, campaign, etc.
|
||||
FirstSeen time.Time `json:"first_seen"`
|
||||
LastSeen time.Time `json:"last_seen"`
|
||||
Confidence float64 `json:"confidence"` // 0.0-1.0
|
||||
|
|
@ -46,31 +50,31 @@ type IOC struct {
|
|||
|
||||
// ThreatFeed represents a configured threat intelligence source.
|
||||
type ThreatFeed struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
Type string `json:"type"` // stix, csv, json
|
||||
Enabled bool `json:"enabled"`
|
||||
Interval time.Duration `json:"interval"`
|
||||
APIKey string `json:"api_key,omitempty"`
|
||||
LastFetch time.Time `json:"last_fetch"`
|
||||
IOCCount int `json:"ioc_count"`
|
||||
LastError string `json:"last_error,omitempty"`
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
Type string `json:"type"` // stix, csv, json
|
||||
Enabled bool `json:"enabled"`
|
||||
Interval time.Duration `json:"interval"`
|
||||
APIKey string `json:"api_key,omitempty"`
|
||||
LastFetch time.Time `json:"last_fetch"`
|
||||
IOCCount int `json:"ioc_count"`
|
||||
LastError string `json:"last_error,omitempty"`
|
||||
}
|
||||
|
||||
// ─── Threat Intel Store ─────────────────────────────────
|
||||
|
||||
// ThreatIntelStore manages IOCs from multiple feeds.
|
||||
type ThreatIntelStore struct {
|
||||
mu sync.RWMutex
|
||||
iocs map[string]*IOC // key: type:value
|
||||
feeds []ThreatFeed
|
||||
mu sync.RWMutex
|
||||
iocs map[string]*IOC // key: type:value
|
||||
feeds []ThreatFeed
|
||||
client *http.Client
|
||||
|
||||
// Stats
|
||||
TotalIOCs int `json:"total_iocs"`
|
||||
TotalFeeds int `json:"total_feeds"`
|
||||
TotalIOCs int `json:"total_iocs"`
|
||||
TotalFeeds int `json:"total_feeds"`
|
||||
LastRefresh time.Time `json:"last_refresh"`
|
||||
MatchesFound int64 `json:"matches_found"`
|
||||
MatchesFound int64 `json:"matches_found"`
|
||||
}
|
||||
|
||||
// NewThreatIntelStore creates an empty threat intel store.
|
||||
|
|
|
|||
|
|
@ -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 soc
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 webhook provides outbound SOAR webhook notifications
|
||||
// for the SOC pipeline. Fires HTTP POST on incident creation/update.
|
||||
package soc
|
||||
|
|
@ -38,8 +42,8 @@ type WebhookConfig struct {
|
|||
type WebhookPayload struct {
|
||||
EventType string `json:"event_type"` // incident_created, incident_updated, sensor_offline
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Source string `json:"source"`
|
||||
Data json.RawMessage `json:"data"`
|
||||
Source string `json:"source"`
|
||||
Data json.RawMessage `json:"data"`
|
||||
}
|
||||
|
||||
// WebhookResult tracks delivery status per endpoint.
|
||||
|
|
@ -80,8 +84,6 @@ func NewWebhookNotifier(config WebhookConfig) *WebhookNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// NotifyIncident sends an incident webhook to all configured endpoints.
|
||||
// Non-blocking: fires goroutines for each endpoint.
|
||||
func (w *WebhookNotifier) NotifyIncident(eventType string, incident *domsoc.Incident) []WebhookResult {
|
||||
|
|
@ -105,7 +107,7 @@ func (w *WebhookNotifier) NotifyIncident(eventType string, incident *domsoc.Inci
|
|||
EventType: eventType,
|
||||
Timestamp: time.Now().UTC(),
|
||||
Source: "sentinel-soc",
|
||||
Data: data,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
body, err := json.Marshal(payload)
|
||||
|
|
@ -151,7 +153,7 @@ func (w *WebhookNotifier) NotifySensorOffline(sensor domsoc.Sensor) []WebhookRes
|
|||
EventType: "sensor_offline",
|
||||
Timestamp: time.Now().UTC(),
|
||||
Source: "sentinel-soc",
|
||||
Data: data,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(payload)
|
||||
|
|
|
|||
|
|
@ -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 tools — Apathy Detection and Apoptosis Recovery (DIP H1.4).
|
||||
//
|
||||
// This file implements:
|
||||
|
|
|
|||
|
|
@ -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 tools
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 tools
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
// 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 tools
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/sqlite"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/sqlite"
|
||||
)
|
||||
|
||||
func newTestCausalService(t *testing.T) *CausalService {
|
||||
|
|
|
|||
|
|
@ -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 tools
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
// 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 tools
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/sqlite"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/sqlite"
|
||||
)
|
||||
|
||||
func newTestCrystalService(t *testing.T) *CrystalService {
|
||||
|
|
|
|||
|
|
@ -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 tools
|
||||
|
||||
// DecisionRecorder is the interface for recording tamper-evident decisions (v3.7).
|
||||
|
|
|
|||
|
|
@ -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 tools
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 tools provides application-level tool services that bridge
|
||||
// domain logic with MCP tool handlers.
|
||||
package tools
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
// 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 tools
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/memory"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/sqlite"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/memory"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/sqlite"
|
||||
)
|
||||
|
||||
func newTestFactService(t *testing.T) *FactService {
|
||||
|
|
|
|||
|
|
@ -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 tools provides application-level tool services.
|
||||
// This file adds the Intent Distiller MCP tool integration (DIP H0.2).
|
||||
package tools
|
||||
|
|
|
|||
|
|
@ -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 tools
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 tools
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
// 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 tools
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/session"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/sqlite"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/session"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/sqlite"
|
||||
)
|
||||
|
||||
func newTestSessionService(t *testing.T) *SessionService {
|
||||
|
|
|
|||
|
|
@ -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 tools
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 tools
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
// 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 tools
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/sqlite"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/syntrex-lab/gomcp/internal/infrastructure/sqlite"
|
||||
)
|
||||
|
||||
func newTestSystemService(t *testing.T) *SystemService {
|
||||
|
|
|
|||
|
|
@ -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 config
|
||||
|
||||
import (
|
||||
|
|
@ -10,34 +14,34 @@ import (
|
|||
|
||||
// Config is the root configuration loaded from syntrex.yaml (§19.3, §21).
|
||||
type Config struct {
|
||||
Server ServerConfig `yaml:"server"`
|
||||
SOC SOCConfig `yaml:"soc"`
|
||||
RBAC RBACConfig `yaml:"rbac"`
|
||||
Webhooks []WebhookConfig `yaml:"webhooks"`
|
||||
Server ServerConfig `yaml:"server"`
|
||||
SOC SOCConfig `yaml:"soc"`
|
||||
RBAC RBACConfig `yaml:"rbac"`
|
||||
Webhooks []WebhookConfig `yaml:"webhooks"`
|
||||
ThreatIntel ThreatIntelConfig `yaml:"threat_intel"`
|
||||
Sovereign SovereignConfig `yaml:"sovereign"`
|
||||
P2P P2PConfig `yaml:"p2p"`
|
||||
Logging LoggingConfig `yaml:"logging"`
|
||||
Sovereign SovereignConfig `yaml:"sovereign"`
|
||||
P2P P2PConfig `yaml:"p2p"`
|
||||
Logging LoggingConfig `yaml:"logging"`
|
||||
}
|
||||
|
||||
// ServerConfig defines HTTP server settings.
|
||||
type ServerConfig struct {
|
||||
Port int `yaml:"port"`
|
||||
ReadTimeout time.Duration `yaml:"read_timeout"`
|
||||
WriteTimeout time.Duration `yaml:"write_timeout"`
|
||||
RateLimitPerMin int `yaml:"rate_limit_per_min"`
|
||||
CORSAllowOrigins []string `yaml:"cors_allow_origins"`
|
||||
Port int `yaml:"port"`
|
||||
ReadTimeout time.Duration `yaml:"read_timeout"`
|
||||
WriteTimeout time.Duration `yaml:"write_timeout"`
|
||||
RateLimitPerMin int `yaml:"rate_limit_per_min"`
|
||||
CORSAllowOrigins []string `yaml:"cors_allow_origins"`
|
||||
}
|
||||
|
||||
// SOCConfig defines SOC pipeline settings (§7).
|
||||
type SOCConfig struct {
|
||||
DataDir string `yaml:"data_dir"`
|
||||
MaxEventsPerHour int `yaml:"max_events_per_hour"`
|
||||
ClusterEnabled bool `yaml:"cluster_enabled"`
|
||||
DataDir string `yaml:"data_dir"`
|
||||
MaxEventsPerHour int `yaml:"max_events_per_hour"`
|
||||
ClusterEnabled bool `yaml:"cluster_enabled"`
|
||||
ClusterEps float64 `yaml:"cluster_eps"`
|
||||
ClusterMinPts int `yaml:"cluster_min_pts"`
|
||||
KillChainEnabled bool `yaml:"kill_chain_enabled"`
|
||||
SSEBufferSize int `yaml:"sse_buffer_size"`
|
||||
ClusterMinPts int `yaml:"cluster_min_pts"`
|
||||
KillChainEnabled bool `yaml:"kill_chain_enabled"`
|
||||
SSEBufferSize int `yaml:"sse_buffer_size"`
|
||||
}
|
||||
|
||||
// RBACConfig defines API key authentication (§17).
|
||||
|
|
@ -65,9 +69,9 @@ type WebhookConfig struct {
|
|||
|
||||
// ThreatIntelConfig defines IOC feed sources (§6).
|
||||
type ThreatIntelConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Enabled bool `yaml:"enabled"`
|
||||
RefreshInterval time.Duration `yaml:"refresh_interval"`
|
||||
Feeds []FeedConfig `yaml:"feeds"`
|
||||
Feeds []FeedConfig `yaml:"feeds"`
|
||||
}
|
||||
|
||||
// FeedConfig is a single threat intel feed.
|
||||
|
|
@ -80,8 +84,8 @@ type FeedConfig struct {
|
|||
|
||||
// SovereignConfig implements §21 — air-gapped deployment mode.
|
||||
type SovereignConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Mode string `yaml:"mode"` // airgap, restricted, open
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Mode string `yaml:"mode"` // airgap, restricted, open
|
||||
DisableExternalAPI bool `yaml:"disable_external_api"`
|
||||
DisableTelemetry bool `yaml:"disable_telemetry"`
|
||||
LocalModelsOnly bool `yaml:"local_models_only"`
|
||||
|
|
@ -108,7 +112,7 @@ type PeerConfig struct {
|
|||
|
||||
// LoggingConfig defines structured logging settings.
|
||||
type LoggingConfig struct {
|
||||
Level string `yaml:"level"` // debug, info, warn, error
|
||||
Level string `yaml:"level"` // debug, info, warn, error
|
||||
Format string `yaml:"format"` // json, text
|
||||
AccessLog bool `yaml:"access_log"`
|
||||
AuditLog bool `yaml:"audit_log"`
|
||||
|
|
|
|||
|
|
@ -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 config
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 alert defines the Alert domain entity and severity levels
|
||||
// for the DIP-Watcher proactive monitoring system.
|
||||
package alert
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
// 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 alert_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/alert"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/alert"
|
||||
)
|
||||
|
||||
func TestAlert_New(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -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 alert
|
||||
|
||||
import "sync"
|
||||
|
|
|
|||
|
|
@ -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 causal defines domain entities for causal reasoning chains.
|
||||
package causal
|
||||
|
||||
|
|
|
|||
|
|
@ -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 causal
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 circuitbreaker implements a state machine that controls
|
||||
// the health of recursive pipelines (DIP H1.1).
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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 circuitbreaker
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -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 context defines domain entities for the Proactive Context Engine.
|
||||
// The engine automatically injects relevant memory facts into every tool response,
|
||||
// ensuring the LLM always has context without explicitly requesting it.
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
// 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 context
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/memory"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/syntrex-lab/gomcp/internal/domain/memory"
|
||||
)
|
||||
|
||||
// --- ScoredFact tests ---
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue