fix: Restore all files lost during destructive rebase
A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.
This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).
Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
151
pca-platform/heuristic-service/internal/config/config.go
Normal file
151
pca-platform/heuristic-service/internal/config/config.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Config holds the heuristic service configuration
|
||||
type Config struct {
|
||||
Port string `json:"port"`
|
||||
RedisURL string `json:"redis_url"`
|
||||
JWTSecret string `json:"jwt_secret"`
|
||||
|
||||
// Heuristic thresholds
|
||||
Thresholds ThresholdConfig `json:"thresholds"`
|
||||
|
||||
// Heuristic weights
|
||||
Weights WeightConfig `json:"weights"`
|
||||
|
||||
// Step-up configuration
|
||||
StepUp StepUpConfig `json:"step_up"`
|
||||
|
||||
// Tick configuration
|
||||
Tick TickConfig `json:"tick"`
|
||||
|
||||
// Compliance settings
|
||||
Compliance ComplianceConfig `json:"compliance"`
|
||||
}
|
||||
|
||||
// ThresholdConfig defines score thresholds
|
||||
type ThresholdConfig struct {
|
||||
ScorePass float64 `json:"score_pass"` // Score to pass without step-up (e.g., 0.7)
|
||||
ScoreChallenge float64 `json:"score_challenge"` // Score below which step-up is required (e.g., 0.4)
|
||||
}
|
||||
|
||||
// WeightConfig defines weights for each heuristic
|
||||
type WeightConfig struct {
|
||||
DwellRatio float64 `json:"dwell_ratio"` // Weight for dwell time ratio
|
||||
ScrollScore float64 `json:"scroll_score"` // Weight for scroll depth
|
||||
PointerVariance float64 `json:"pointer_variance"` // Weight for mouse movement patterns
|
||||
ClickRate float64 `json:"click_rate"` // Weight for click interactions
|
||||
}
|
||||
|
||||
// StepUpConfig defines step-up verification methods
|
||||
type StepUpConfig struct {
|
||||
Methods []string `json:"methods"` // ["webauthn", "pow"]
|
||||
Primary string `json:"primary"` // Preferred method
|
||||
WebAuthn WebAuthnConfig `json:"webauthn"`
|
||||
PoW PoWConfig `json:"pow"`
|
||||
}
|
||||
|
||||
// WebAuthnConfig for WebAuthn step-up
|
||||
type WebAuthnConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
UserVerification string `json:"userVerification"` // "preferred", "required", "discouraged"
|
||||
TimeoutMs int `json:"timeout_ms"`
|
||||
ChallengeEndpoint string `json:"challenge_endpoint"`
|
||||
}
|
||||
|
||||
// PoWConfig for Proof-of-Work step-up
|
||||
type PoWConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Difficulty int `json:"difficulty"` // Number of leading zero bits required
|
||||
MaxDurationMs int `json:"max_duration_ms"` // Max time for PoW computation
|
||||
}
|
||||
|
||||
// TickConfig for periodic tick submissions
|
||||
type TickConfig struct {
|
||||
Endpoint string `json:"endpoint"`
|
||||
IntervalMs int `json:"interval_ms"`
|
||||
}
|
||||
|
||||
// ComplianceConfig for privacy compliance
|
||||
type ComplianceConfig struct {
|
||||
GDPR bool `json:"gdpr"`
|
||||
AnonymizeIP bool `json:"anonymize_ip"`
|
||||
NoCookies bool `json:"no_cookies"`
|
||||
NoPII bool `json:"no_pii"`
|
||||
}
|
||||
|
||||
// PathConfig for path-specific rules
|
||||
type PathConfig struct {
|
||||
MinScore float64 `json:"min_score"`
|
||||
StepUpMethod *string `json:"step_up_method"` // nil means no step-up
|
||||
}
|
||||
|
||||
// DefaultConfig returns a default configuration
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
Port: getEnv("PORT", "8085"),
|
||||
RedisURL: getEnv("REDIS_URL", "redis://localhost:6379"),
|
||||
JWTSecret: getEnv("JWT_SECRET", "pca-secret-change-me"),
|
||||
Thresholds: ThresholdConfig{
|
||||
ScorePass: 0.7,
|
||||
ScoreChallenge: 0.4,
|
||||
},
|
||||
Weights: WeightConfig{
|
||||
DwellRatio: 0.30,
|
||||
ScrollScore: 0.25,
|
||||
PointerVariance: 0.20,
|
||||
ClickRate: 0.25,
|
||||
},
|
||||
StepUp: StepUpConfig{
|
||||
Methods: []string{"webauthn", "pow"},
|
||||
Primary: "webauthn",
|
||||
WebAuthn: WebAuthnConfig{
|
||||
Enabled: true,
|
||||
UserVerification: "preferred",
|
||||
TimeoutMs: 60000,
|
||||
ChallengeEndpoint: "/pca/v1/webauthn-challenge",
|
||||
},
|
||||
PoW: PoWConfig{
|
||||
Enabled: true,
|
||||
Difficulty: 4,
|
||||
MaxDurationMs: 5000,
|
||||
},
|
||||
},
|
||||
Tick: TickConfig{
|
||||
Endpoint: "/pca/v1/tick",
|
||||
IntervalMs: 5000,
|
||||
},
|
||||
Compliance: ComplianceConfig{
|
||||
GDPR: true,
|
||||
AnonymizeIP: true,
|
||||
NoCookies: true,
|
||||
NoPII: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// LoadFromFile loads configuration from a JSON file
|
||||
func LoadFromFile(path string) (*Config, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return DefaultConfig(), nil // Return default if file not found
|
||||
}
|
||||
|
||||
config := DefaultConfig()
|
||||
if err := json.Unmarshal(data, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func getEnv(key, defaultValue string) string {
|
||||
if value := os.Getenv(key); value != "" {
|
||||
return value
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
Reference in New Issue
Block a user