package main import ( "crypto/sha256" "encoding/hex" "encoding/json" "fmt" "net/http" "os" "strings" "git.cin.su/m/Assistant/contracts/capability" "git.cin.su/m/Assistant/contracts/work" ) const verifierIdentity = "deterministic-task-verifier-v1" const genericVerifierIdentity = "deterministic-generic-envelope-verifier-v1" func main() { mux := http.NewServeMux() mux.HandleFunc("GET /healthz", func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"runtime":"task-verifier","status":"ok"}`)) }) mux.HandleFunc("POST /v1/task-evaluations/verify", verifyHandler) mux.HandleFunc("POST /v1/work-graphs/candidates/verify", genericCandidateVerifyHandler) addr := ":8091" if value := strings.TrimSpace(os.Getenv("LISTEN_ADDR")); value != "" { addr = value } if err := http.ListenAndServe(addr, mux); err != nil { panic(err) } } func genericCandidateVerifyHandler(w http.ResponseWriter, r *http.Request) { var request work.GenericCandidateVerificationRequest decoder := json.NewDecoder(http.MaxBytesReader(w, r.Body, 64<<10)) decoder.DisallowUnknownFields() if err := decoder.Decode(&request); err != nil || request.GraphID == "" || request.GraphRevision < 1 || request.NodeID == "" || request.AuthorRunID == "" || request.CandidateID == "" || strings.TrimSpace(request.Summary) == "" || len(request.EvidenceRefs) == 0 { http.Error(w, "invalid generic candidate envelope", http.StatusBadRequest) return } payload := fmt.Sprintf("%s|%s|%d|%s|%s|%s|%s", genericVerifierIdentity, request.GraphID, request.GraphRevision, request.NodeID, request.AuthorRunID, request.CandidateID, strings.Join(evidenceRefStrings(request.EvidenceRefs), "|")) digest := sha256.Sum256([]byte(payload)) writeJSON(w, work.GenericCandidateVerificationResponse{Verified: true, VerificationEvidenceRef: "verification:" + hex.EncodeToString(digest[:]), VerifierIdentity: genericVerifierIdentity, Summary: "candidate attribution and evidence envelope verified; semantic content remains unverified"}) } func evidenceRefStrings(values []work.EvidenceRef) []string { result := make([]string, len(values)) for i, value := range values { result[i] = string(value) } return result } func verifyHandler(w http.ResponseWriter, r *http.Request) { var request capability.TaskCaseVerificationRequest decoder := json.NewDecoder(http.MaxBytesReader(w, r.Body, 64<<10)) decoder.DisallowUnknownFields() if err := decoder.Decode(&request); err != nil || request.CaseID == "" || request.ResponseText == "" || request.EvidenceArtifactRef == "" || request.LatencyMicros < 0 || (request.Verification.Mode != capability.TaskCaseVerificationExactText && request.Verification.Mode != capability.TaskCaseVerificationJSONFieldEquals) || (request.Verification.Mode == capability.TaskCaseVerificationJSONFieldEquals && request.Verification.FieldPath == "") || request.Verification.ExpectedText == "" || request.Verification.MinimumQualityMillis < 0 || request.Verification.MinimumQualityMillis > 1000 { http.Error(w, "invalid task verification request", http.StatusBadRequest) return } matched := matches(request) quality := int64(0) result := capability.EvaluationUnsupported if matched { quality = request.Verification.MinimumQualityMillis if quality == 0 { quality = 1000 } result = capability.EvaluationSupported } evidence := verificationEvidence(request, matched) writeJSON(w, capability.TaskCaseVerificationResponse{CaseID: request.CaseID, Result: result, QualityScoreMillis: quality, LatencyMicros: request.LatencyMicros, EvidenceArtifactRef: request.EvidenceArtifactRef, VerificationEvidenceRef: evidence, VerifierIdentity: verifierIdentity}) } func verificationEvidence(request capability.TaskCaseVerificationRequest, matched bool) string { payload := fmt.Sprintf("%s|%s|%s|%s|%s|%t", verifierIdentity, request.CaseID, request.EvidenceArtifactRef, request.Verification.Mode, request.Verification.FieldPath, matched) digest := sha256.Sum256([]byte(payload)) return "verification:" + hex.EncodeToString(digest[:]) } func matches(request capability.TaskCaseVerificationRequest) bool { if request.Verification.Mode == capability.TaskCaseVerificationExactText { return strings.TrimSpace(request.ResponseText) == strings.TrimSpace(request.Verification.ExpectedText) } var document map[string]json.RawMessage if json.Unmarshal([]byte(request.ResponseText), &document) != nil { return false } value, ok := document[request.Verification.FieldPath] return ok && strings.TrimSpace(string(value)) == strings.TrimSpace(request.Verification.ExpectedText) } func writeJSON(w http.ResponseWriter, value any) { w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(value) }