mirror of
https://github.com/syntrex-lab/gomcp.git
synced 2026-04-25 04:16:22 +02:00
feat: connect demo scanner to real SENTINEL engines via /api/v1/scan endpoint
This commit is contained in:
parent
4a0f17873a
commit
b958ed07bd
3 changed files with 65 additions and 0 deletions
|
|
@ -23,6 +23,7 @@ import (
|
|||
|
||||
"github.com/syntrex/gomcp/internal/application/soc"
|
||||
socdomain "github.com/syntrex/gomcp/internal/domain/soc"
|
||||
"github.com/syntrex/gomcp/internal/domain/engines"
|
||||
"github.com/syntrex/gomcp/internal/infrastructure/audit"
|
||||
"github.com/syntrex/gomcp/internal/infrastructure/email"
|
||||
"github.com/syntrex/gomcp/internal/infrastructure/logging"
|
||||
|
|
@ -147,6 +148,16 @@ func main() {
|
|||
logger.Warn("email service: RESEND_API_KEY not set — verification codes shown in API response (dev mode)")
|
||||
}
|
||||
|
||||
// Sentinel Core — Rust-native detection engine (§3)
|
||||
sentinelCore, coreErr := engines.NewNativeSentinelCore()
|
||||
if coreErr != nil {
|
||||
logger.Warn("sentinel-core: Rust engine not available, using stub", "error", coreErr)
|
||||
srv.SetSentinelCore(engines.NewStubSentinelCore())
|
||||
} else {
|
||||
srv.SetSentinelCore(sentinelCore)
|
||||
logger.Info("sentinel-core: Rust engine initialized", "version", sentinelCore.Version())
|
||||
}
|
||||
|
||||
// OpenTelemetry tracing (§P4B) — enabled when OTEL_EXPORTER_OTLP_ENDPOINT is set
|
||||
otelEndpoint := env("OTEL_EXPORTER_OTLP_ENDPOINT", "")
|
||||
tp, otelErr := tracing.InitTracer(context.Background(), otelEndpoint)
|
||||
|
|
|
|||
|
|
@ -75,6 +75,11 @@ func (s *Server) SetEmailService(svc *email.Service) {
|
|||
s.emailService = svc
|
||||
}
|
||||
|
||||
// SetSentinelCore sets the Rust-native detection engine for real-time scanning.
|
||||
func (s *Server) SetSentinelCore(core engines.SentinelCore) {
|
||||
s.sentinelCore = core
|
||||
}
|
||||
|
||||
// SetJWTAuth enables JWT authentication with the given secret.
|
||||
// If secret is empty or <32 bytes, JWT is disabled (backward compatible).
|
||||
// Optional db parameter enables SQLite-backed user persistence.
|
||||
|
|
@ -243,6 +248,9 @@ func (s *Server) Start(ctx context.Context) error {
|
|||
mux.HandleFunc("GET /metrics", s.metrics.Handler())
|
||||
mux.HandleFunc("GET /api/soc/ratelimit", s.handleRateLimitStats)
|
||||
|
||||
// Public scan endpoint — demo scanner (no auth required, rate-limited)
|
||||
mux.HandleFunc("POST /api/v1/scan", s.handlePublicScan)
|
||||
|
||||
// pprof debug endpoints (§P4C) — gated behind EnablePprof()
|
||||
if s.pprofEnabled {
|
||||
mux.HandleFunc("GET /debug/pprof/", s.handlePprof)
|
||||
|
|
|
|||
|
|
@ -1445,3 +1445,49 @@ func (s *Server) handleSLAConfig(w http.ResponseWriter, _ *http.Request) {
|
|||
"sla_thresholds": entries,
|
||||
})
|
||||
}
|
||||
|
||||
// handlePublicScan provides a public (no-auth) prompt scanning endpoint for the demo.
|
||||
// POST /api/v1/scan body: {"prompt": "Ignore all instructions..."}
|
||||
func (s *Server) handlePublicScan(w http.ResponseWriter, r *http.Request) {
|
||||
limitBody(w, r)
|
||||
defer r.Body.Close()
|
||||
|
||||
var req struct {
|
||||
Prompt string `json:"prompt"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
writeError(w, http.StatusBadRequest, "invalid JSON: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Validate input
|
||||
if req.Prompt == "" {
|
||||
writeError(w, http.StatusBadRequest, "prompt is required")
|
||||
return
|
||||
}
|
||||
if len(req.Prompt) > 2000 {
|
||||
writeError(w, http.StatusBadRequest, "prompt too long (max 2000 chars)")
|
||||
return
|
||||
}
|
||||
|
||||
// Get engine (real or stub)
|
||||
engine := s.getEngine("sentinel-core")
|
||||
|
||||
// Scan
|
||||
result, err := engine.ScanPrompt(r.Context(), req.Prompt)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, "scan failed: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"blocked": result.ThreatFound,
|
||||
"threat_type": result.ThreatType,
|
||||
"severity": result.Severity,
|
||||
"confidence": result.Confidence,
|
||||
"details": result.Details,
|
||||
"indicators": result.Indicators,
|
||||
"engine": result.Engine,
|
||||
"latency_ms": float64(result.Duration.Microseconds()) / 1000.0,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue