//go:build llm_script package main import ( "fmt" "net/http" "os" "path/filepath" "strings" "time" ) type deepseekNewsSignatureGuardConfig struct { URL string Fixture string SnapshotDir string BaselinePath string Timeout time.Duration AllowBootstrap bool } type deepseekNewsSignatureGuardResult struct { SnapshotPath string SignaturePath string BaselinePath string DriftDetected bool BaselineInitialized bool PreviousBaselineHash string CurrentSignature deepseekNewsStructureSignature } const defaultDeepSeekNewsFetchURL = "https://api-docs.deepseek.com/news/news250120" func runDeepSeekNewsSignatureGuard(cfg deepseekNewsSignatureGuardConfig, now time.Time) (deepseekNewsSignatureGuardResult, error) { snapshotDir := cfg.SnapshotDir if snapshotDir == "" { snapshotDir = filepath.Join("logs", "deepseek-news-snapshots") } if err := os.MkdirAll(snapshotDir, 0o755); err != nil { return deepseekNewsSignatureGuardResult{}, fmt.Errorf("mkdir snapshot dir: %w", err) } snapshotPath, signaturePath := resolveDeepSeekNewsSnapshotPaths("", "", snapshotDir, now) baselinePath := cfg.BaselinePath if baselinePath == "" { baselinePath = filepath.Join(snapshotDir, "baseline.signature.json") } client := &http.Client{Timeout: cfg.Timeout} raw, err := fetchSubscriptionPage(cfg.URL, cfg.Fixture, client) if err != nil { return deepseekNewsSignatureGuardResult{}, err } current, err := writeDeepSeekNewsSnapshotArtifacts(raw, cfg.URL, snapshotPath, signaturePath, now) if err != nil { return deepseekNewsSignatureGuardResult{}, err } result := deepseekNewsSignatureGuardResult{ SnapshotPath: snapshotPath, SignaturePath: signaturePath, BaselinePath: baselinePath, CurrentSignature: current, } previous, err := readDeepSeekNewsStructureSignature(baselinePath) if err != nil { if os.IsNotExist(err) { if !cfg.AllowBootstrap { return result, fmt.Errorf("deepseek news baseline missing: %s", baselinePath) } if err := copyFileCommon(signaturePath, baselinePath); err != nil { return result, fmt.Errorf("initialize baseline: %w", err) } result.BaselineInitialized = true return result, nil } return result, err } result.PreviousBaselineHash = previous.StructureSHA256 if previous.StructureSHA256 != current.StructureSHA256 { result.DriftDetected = true return result, fmt.Errorf( "deepseek news structure drift detected: baseline=%s current=%s baseline_path=%s signature_path=%s snapshot_path=%s", previous.StructureSHA256, current.StructureSHA256, baselinePath, signaturePath, snapshotPath, ) } return result, nil } func formatDeepSeekNewsSignatureGuardSummary(result deepseekNewsSignatureGuardResult) string { return fmt.Sprintf( "source=deepseek-news-signature-guard drift=%t baseline_initialized=%t structure_sha256=%s previous_baseline_sha256=%s snapshot_out=%s signature_out=%s baseline_path=%s", result.DriftDetected, result.BaselineInitialized, result.CurrentSignature.StructureSHA256, emptyIfBlank(result.PreviousBaselineHash), result.SnapshotPath, result.SignaturePath, result.BaselinePath, ) } func buildDeepSeekNewsSignatureAuditRecord(cfg deepseekNewsSignatureGuardConfig, result deepseekNewsSignatureGuardResult, checkedAt time.Time, runErr error) officialImportSignatureAuditRecord { record := officialImportSignatureAuditRecord{ SourceKey: "deepseek_news_signature", CheckedAt: checkedAt, Status: officialImportSignatureAuditStatus(result.DriftDetected, result.BaselineInitialized, runErr), DriftDetected: result.DriftDetected, BaselineInitialized: result.BaselineInitialized, SourceURL: strings.TrimSpace(cfg.URL), FixturePath: strings.TrimSpace(cfg.Fixture), SnapshotPath: strings.TrimSpace(result.SnapshotPath), SignaturePath: strings.TrimSpace(result.SignaturePath), BaselinePath: strings.TrimSpace(result.BaselinePath), StructureSHA256: strings.TrimSpace(result.CurrentSignature.StructureSHA256), PreviousStructureSHA256: strings.TrimSpace(result.PreviousBaselineHash), ByteSize: result.CurrentSignature.ByteSize, ErrorMessage: errorMessageText(runErr), } if hasDeepSeekNewsStructureSignature(result.CurrentSignature) { signatureCopy := result.CurrentSignature record.SignaturePayload = &signatureCopy } return record } func persistDeepSeekNewsSignatureAuditIfConfigured(cfg deepseekNewsSignatureGuardConfig, result deepseekNewsSignatureGuardResult, checkedAt time.Time, runErr error) error { return persistOfficialImportSignatureAuditIfConfigured(buildDeepSeekNewsSignatureAuditRecord(cfg, result, checkedAt, runErr)) }