package openai import ( "context" "encoding/json" "errors" "fmt" "io" "net" "net/http" "net/http/httptest" "strings" "sync/atomic" "testing" "time" toki "git.toki-labs.com/toki/proto-socket/go" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/testutil" dto "github.com/prometheus/client_model/go" "go.uber.org/zap" "go.uber.org/zap/zapcore" "go.uber.org/zap/zaptest/observer" "google.golang.org/protobuf/proto" "iop/apps/edge/internal/authprojection" edgenode "iop/apps/edge/internal/node" edgeservice "iop/apps/edge/internal/service" "iop/packages/go/config" iop "iop/proto/gen/iop" ) const ( testSingleRequestModel = "virtual-single-request" testSingleRequestToken = "single-request-token" ) type anthropicSingleRequestExecutorFunc func(context.Context, edgeservice.SingleRequestRequest, edgeservice.SingleRequestController) error func (f anthropicSingleRequestExecutorFunc) ExecuteSingleRequest( ctx context.Context, req edgeservice.SingleRequestRequest, ctrl edgeservice.SingleRequestController, ) error { return f(ctx, req, ctrl) } // newAdmittedAnthropicSingleRequestService builds the same catalog and ready // owner preconditions that the public service requires in production. Endpoint // tests must cross this boundary rather than using a zero-value Service. func newAdmittedAnthropicSingleRequestService( t *testing.T, executor edgeservice.SingleRequestExecutor, workspaceRef string, ) *edgeservice.Service { t.Helper() const nodeID = "workspace-node" registry := edgenode.NewRegistry() registry.Register(&edgenode.NodeEntry{NodeID: nodeID, Alias: "workspace"}) store := edgenode.NewNodeStore() store.Add(&edgenode.NodeRecord{ ID: nodeID, Alias: "workspace", Token: "workspace-node-token", Workspaces: []config.WorkspaceDefinition{{ Ref: workspaceRef, Platform: "darwin", Root: "/Users/operator/project", Operations: []config.WorkspaceOperation{config.WorkspaceOpRead}, MaxReadBytes: 4096, }}, }) svc := edgeservice.New(registry, nil) svc.SetNodeStore(store) svc.SetSingleRequestExecutor(executor) return svc } func newAnthropicSingleRequestServer(t *testing.T, svc runService) *Server { t.Helper() now := time.Date(2026, 8, 6, 12, 0, 0, 0, time.UTC) cache := authprojection.NewCache(authprojection.DefaultLimits(), func() time.Time { return now }) routes := map[string]authprojection.Route{ "plan": { RouteID: "public-plan", PrincipalRef: "principal-1", CredentialSlotRef: "slot-plan", ProfileID: "profile-plan", UpstreamModel: "served-plan", ResourceSelector: "default", }, "work": { RouteID: "public-work", PrincipalRef: "principal-1", CredentialSlotRef: "slot-work", ProfileID: "profile-work", UpstreamModel: "served-work", ResourceSelector: "default", }, "review": { RouteID: "public-review", PrincipalRef: "principal-1", CredentialSlotRef: "slot-review", ProfileID: "profile-review", UpstreamModel: "served-review", ResourceSelector: "default", }, } if err := cache.Apply(makeTestProjection( 1, now, time.Hour, map[string]string{testSingleRequestToken: "principal-1"}, routes, )); err != nil { t.Fatalf("apply projection: %v", err) } deterministicCounter := config.TokenCounterConf{Mode: config.TokenCounterDeterministic} srv := NewServer(config.EdgeOpenAIConf{}, svc, nil) setManagedPrincipalProjection(srv, cache) srv.SetExecutionPresets([]config.ExecutionPreset{validSingleRequestPreset()}) srv.SetModelCatalog([]config.ModelCatalogEntry{ {ID: testSingleRequestModel, ExecutionPreset: "preset-single-request"}, {ID: "plan-model", Providers: map[string]string{"provider-plan": "served-plan"}, TokenCounter: &deterministicCounter}, {ID: "work-model", Providers: map[string]string{"provider-work": "served-work"}}, {ID: "review-model", Providers: map[string]string{"provider-review": "served-review"}}, }) return srv } func newAnthropicSingleRequestHTTPReq(t *testing.T, ctx context.Context, target, path, body string) *http.Request { t.Helper() req, err := http.NewRequestWithContext(ctx, http.MethodPost, target+path, strings.NewReader(body)) if err != nil { t.Fatalf("new request: %v", err) } req.Header.Set("Authorization", "Bearer "+testSingleRequestToken) req.Header.Set(anthropicVersionHeader, anthropicSupportedVersion) req.Header.Set("Content-Type", "application/json") return req } func serveAnthropicSingleRequest(t *testing.T, srv *Server, ctx context.Context, path, body string, w http.ResponseWriter) { t.Helper() req := newAnthropicSingleRequestHTTPReq(t, ctx, "http://edge.invalid", path, body) srv.routes().ServeHTTP(w, req) } func TestAnthropicPreIngressRejectionClassificationIsClosed(t *testing.T) { t.Parallel() tests := []struct { name string err string want anthropicPreIngressRejectionClass }{ {name: "unsupported beta", err: `unsupported anthropic-beta "SECRET_BETA"`, want: anthropicPreIngressUnsupportedBeta}, {name: "unknown field", err: `decode Messages request: json: unknown field "SECRET_FIELD"`, want: anthropicPreIngressUnknownField}, {name: "thinking", err: `thinking.display SECRET_DISPLAY`, want: anthropicPreIngressInvalidThinking}, {name: "output config", err: `output_config.effort SECRET_EFFORT`, want: anthropicPreIngressInvalidOutput}, {name: "generic", err: `SECRET_UNCLASSIFIED`, want: anthropicPreIngressInvalidRequest}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { t.Parallel() if got := classifyAnthropicPreIngressRejection(errors.New(test.err)); got != test.want { t.Fatalf("class=%q want=%q", got, test.want) } }) } } func TestAnthropicPreIngressRejectionLogOmitsArbitraryInput(t *testing.T) { t.Parallel() service := newAdmittedAnthropicSingleRequestService(t, anthropicSingleRequestExecutorFunc( func(context.Context, edgeservice.SingleRequestRequest, edgeservice.SingleRequestController) error { return nil }, ), "workspace") core, logs := observer.New(zap.InfoLevel) srv := newAnthropicSingleRequestServer(t, service) srv.logger = zap.New(core) tests := []struct { name string marker string body string header string want anthropicPreIngressRejectionClass }{ { name: "unknown field", marker: "SECRET_FIELD_MARKER", body: `{"model":"` + testSingleRequestModel + `","max_tokens":16,"messages":[{"role":"user","content":"hello"}],"SECRET_FIELD_MARKER":true}`, want: anthropicPreIngressUnknownField, }, { name: "unsupported beta", marker: "SECRET_BETA_MARKER", body: `{"model":"` + testSingleRequestModel + `","max_tokens":16,"messages":[{"role":"user","content":"hello"}]}`, header: "SECRET_BETA_MARKER", want: anthropicPreIngressUnsupportedBeta, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { logs.TakeAll() recorder := httptest.NewRecorder() request := newAnthropicSingleRequestHTTPReq(t, context.Background(), "http://edge.invalid", "/v1/messages", test.body) if test.header != "" { request.Header.Set(anthropicBetaHeader, test.header) } srv.routes().ServeHTTP(recorder, request) if recorder.Code != http.StatusBadRequest { t.Fatalf("status=%d body=%s", recorder.Code, recorder.Body.String()) } entries := logs.FilterMessage(anthropicPreIngressRejectionLogMessage).All() if len(entries) != 1 { t.Fatalf("log entries=%d want=1", len(entries)) } fields := entries[0].ContextMap() if got := fields["rejection_class"]; got != string(test.want) { t.Fatalf("rejection_class=%v want=%q", got, test.want) } if fields["surface"] != "messages" || fields["http_status"] != int64(http.StatusBadRequest) { t.Fatalf("log fields=%v", fields) } if strings.Contains(fmt.Sprint(entries[0].Message, fields), test.marker) { t.Fatal("arbitrary input leaked into pre-ingress log") } }) } } func submitAnthropicSingleRequestLifecycle( req edgeservice.SingleRequestRequest, ctrl edgeservice.SingleRequestController, result string, ) error { type step struct { stage edgeservice.SingleRequestState saved edgeservice.SingleRequestState } steps := []step{ {stage: edgeservice.SingleRequestStatePlanning}, {stage: edgeservice.SingleRequestStateWorking}, {stage: edgeservice.SingleRequestStateReviewing}, {stage: edgeservice.SingleRequestStateRepairing}, {stage: edgeservice.SingleRequestStateFinalizing}, } for index, item := range steps { envelope := edgeservice.SingleRequestEnvelope{ RequestID: req.RequestID, Sequence: uint64(index + 1), Stage: item.stage, SavedStage: item.saved, Message: "PRIVATE_STAGE_SENTINEL", } if item.stage == edgeservice.SingleRequestStateFinalizing { envelope.Result = &edgeservice.SingleRequestResult{Output: result} } if err := ctrl.SubmitEnvelope(envelope); err != nil { return err } } return nil } func TestAnthropicSingleRequestUsesOnePost(t *testing.T) { const ( privatePrompt = "PRIVATE_CALLER_PROMPT_SENTINEL" finalOutput = "workspace task completed" ) var calls atomic.Int32 requestCh := make(chan edgeservice.SingleRequestRequest, 1) controllerCh := make(chan edgeservice.SingleRequestController, 1) executor := anthropicSingleRequestExecutorFunc(func( _ context.Context, req edgeservice.SingleRequestRequest, ctrl edgeservice.SingleRequestController, ) error { calls.Add(1) requestCh <- req if err := submitAnthropicSingleRequestLifecycle(req, ctrl, finalOutput); err != nil { return err } controllerCh <- ctrl return nil }) svc := newAdmittedAnthropicSingleRequestService(t, executor, "ws-opaque-ref") srv := newAnthropicSingleRequestServer(t, svc) httpServer := httptest.NewServer(srv.routes()) defer httpServer.Close() before := testutil.ToFloat64(singleRequestIngressTotal) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() body := `{"model":"` + testSingleRequestModel + `","max_tokens":128,"messages":[{"role":"user","content":"` + privatePrompt + `"}],"tools":[{"name":"caller_tool","input_schema":{"type":"object"}}]}` req := newAnthropicSingleRequestHTTPReq(t, ctx, httpServer.URL, "/v1/messages", body) response, err := httpServer.Client().Do(req) if err != nil { t.Fatalf("POST /v1/messages: %v", err) } defer response.Body.Close() if response.StatusCode != http.StatusOK { payload, _ := io.ReadAll(response.Body) t.Fatalf("status=%d body=%s", response.StatusCode, payload) } if got := response.Header.Get("Content-Type"); !strings.HasPrefix(got, "application/json") { t.Fatalf("content-type=%q, want buffered application/json terminal", got) } var terminal anthropicMessageResponse decoder := json.NewDecoder(response.Body) if err := decoder.Decode(&terminal); err != nil { t.Fatalf("decode terminal: %v", err) } var extra json.RawMessage if err := decoder.Decode(&extra); err != io.EOF { t.Fatalf("expected exactly one JSON terminal, trailing decode error=%v value=%s", err, extra) } if terminal.Model != testSingleRequestModel || terminal.Type != "message" || terminal.Role != "assistant" { t.Fatalf("public terminal identity mismatch: %+v", terminal) } if terminal.StopReason == nil || *terminal.StopReason != "end_turn" { t.Fatalf("stop_reason=%v, want end_turn", terminal.StopReason) } if len(terminal.Content) != 1 || terminal.Content[0]["type"] != "text" || terminal.Content[0]["text"] != finalOutput { t.Fatalf("terminal content=%+v, want one sanitized text block", terminal.Content) } encoded, err := json.Marshal(terminal) if err != nil { t.Fatal(err) } for _, privateValue := range []string{ privatePrompt, "PRIVATE_STAGE_SENTINEL", "caller_tool", "tool_use", "ws-opaque-ref", "plan-model", "provider-plan", "slot-plan", } { if strings.Contains(string(encoded), privateValue) { t.Fatalf("terminal leaked %q: %s", privateValue, encoded) } } if got := testutil.ToFloat64(singleRequestIngressTotal) - before; got != 1 { t.Fatalf("single-request ingress counter delta=%v, want 1", got) } if got := calls.Load(); got != 1 { t.Fatalf("executor calls=%d, want 1", got) } captured := <-requestCh if captured.Binding == nil || captured.Binding.PublicModel != testSingleRequestModel { t.Fatalf("captured immutable binding=%+v", captured.Binding) } if workspace := captured.Binding.Workspace; workspace == nil || workspace.Ref != "ws-opaque-ref" || workspace.NodeID != "workspace-node" || workspace.ConnectionGeneration == 0 || len(workspace.OperationIDs) != 1 || workspace.OperationIDs[0] != string(config.WorkspaceOpRead) { t.Fatalf("captured workspace projection=%#v, want frozen ready read capability", workspace) } if !strings.Contains(captured.Prompt, privatePrompt) { t.Fatalf("executor did not receive immutable caller input: %q", captured.Prompt) } controller := <-controllerCh if got := controller.State(); got != edgeservice.SingleRequestStateCompleted { t.Fatalf("terminal acknowledgement state=%s, want completed", got) } families, err := prometheus.DefaultGatherer.Gather() if err != nil { t.Fatalf("gather metrics: %v", err) } foundMetric := false for _, family := range families { if family.GetName() != "iop_anthropic_single_request_ingress_total" { continue } foundMetric = true for _, metric := range family.Metric { if len(metric.Label) != 0 { t.Fatalf("single-request ingress metric has request-derived labels: %+v", metric.Label) } } } if !foundMetric { t.Fatal("registered single-request ingress metric was not gathered") } } func TestAnthropicSingleRequestErrorCancelMatrix(t *testing.T) { const privatePartial = "PRIVATE_PARTIAL_STAGE_OUTPUT" tests := []struct { name string disposition edgeservice.SingleRequestTerminalDisposition wantStatus int wantStop string wantType string wantMessage string silent bool }{ {name: "end turn", disposition: edgeservice.SingleRequestTerminalDisposition{Kind: edgeservice.SingleRequestTerminalEndTurn}, wantStatus: http.StatusOK, wantStop: "end_turn"}, {name: "length", disposition: edgeservice.SingleRequestTerminalDisposition{Kind: edgeservice.SingleRequestTerminalLength}, wantStatus: http.StatusOK, wantStop: "max_tokens"}, {name: "cancelled", disposition: edgeservice.SingleRequestTerminalDisposition{Kind: edgeservice.SingleRequestTerminalCancelled}, silent: true}, {name: "provider", disposition: edgeservice.SingleRequestTerminalDisposition{Kind: edgeservice.SingleRequestTerminalError, ErrorClass: edgeservice.SingleRequestTerminalErrorProvider}, wantStatus: http.StatusBadGateway, wantType: "api_error", wantMessage: "single-request execution failed"}, {name: "validation", disposition: edgeservice.SingleRequestTerminalDisposition{Kind: edgeservice.SingleRequestTerminalError, ErrorClass: edgeservice.SingleRequestTerminalErrorValidation}, wantStatus: http.StatusBadRequest, wantType: "invalid_request_error", wantMessage: "single-request execution was rejected"}, {name: "timeout", disposition: edgeservice.SingleRequestTerminalDisposition{Kind: edgeservice.SingleRequestTerminalError, ErrorClass: edgeservice.SingleRequestTerminalErrorTimeout}, wantStatus: http.StatusBadGateway, wantType: "api_error", wantMessage: "single-request execution timed out"}, {name: "budget", disposition: edgeservice.SingleRequestTerminalDisposition{Kind: edgeservice.SingleRequestTerminalError, ErrorClass: edgeservice.SingleRequestTerminalErrorBudget}, wantStatus: http.StatusBadGateway, wantType: "api_error", wantMessage: "single-request execution failed"}, {name: "repetition", disposition: edgeservice.SingleRequestTerminalDisposition{Kind: edgeservice.SingleRequestTerminalError, ErrorClass: edgeservice.SingleRequestTerminalErrorRepetition}, wantStatus: http.StatusBadGateway, wantType: "api_error", wantMessage: "single-request execution failed"}, {name: "malformed", disposition: edgeservice.SingleRequestTerminalDisposition{Kind: edgeservice.SingleRequestTerminalError, ErrorClass: edgeservice.SingleRequestTerminalErrorMalformed}, wantStatus: http.StatusBadGateway, wantType: "api_error", wantMessage: "single-request execution failed"}, {name: "context", disposition: edgeservice.SingleRequestTerminalDisposition{Kind: edgeservice.SingleRequestTerminalError, ErrorClass: edgeservice.SingleRequestTerminalErrorContext}, wantStatus: http.StatusBadRequest, wantType: "invalid_request_error", wantMessage: "single-request context limit exceeded"}, {name: "internal tool", disposition: edgeservice.SingleRequestTerminalDisposition{Kind: edgeservice.SingleRequestTerminalError, ErrorClass: edgeservice.SingleRequestTerminalErrorInternalTool}, wantStatus: http.StatusBadGateway, wantType: "api_error", wantMessage: "single-request execution failed"}, {name: "workspace cleanup", disposition: edgeservice.SingleRequestTerminalDisposition{Kind: edgeservice.SingleRequestTerminalError, ErrorClass: edgeservice.SingleRequestTerminalErrorWorkspaceCleanup}, wantStatus: http.StatusBadGateway, wantType: "api_error", wantMessage: "single-request execution failed"}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { executor := anthropicSingleRequestExecutorFunc(func( _ context.Context, req edgeservice.SingleRequestRequest, ctrl edgeservice.SingleRequestController, ) error { if err := ctrl.SubmitEnvelope(edgeservice.SingleRequestEnvelope{RequestID: req.RequestID, Sequence: 1, Stage: edgeservice.SingleRequestStatePlanning}); err != nil { return err } switch tc.disposition.Kind { case edgeservice.SingleRequestTerminalEndTurn, edgeservice.SingleRequestTerminalLength: for sequence, stage := range []edgeservice.SingleRequestState{edgeservice.SingleRequestStateWorking, edgeservice.SingleRequestStateReviewing} { if err := ctrl.SubmitEnvelope(edgeservice.SingleRequestEnvelope{RequestID: req.RequestID, Sequence: uint64(sequence + 2), Stage: stage}); err != nil { return err } } output := "safe final result" if tc.disposition.Kind == edgeservice.SingleRequestTerminalLength { output = privatePartial } return ctrl.SubmitEnvelope(edgeservice.SingleRequestEnvelope{ RequestID: req.RequestID, Sequence: 4, Stage: edgeservice.SingleRequestStateFinalizing, Result: &edgeservice.SingleRequestResult{Output: output, Terminal: tc.disposition}, }) case edgeservice.SingleRequestTerminalCancelled: return ctrl.SubmitEnvelope(edgeservice.SingleRequestEnvelope{RequestID: req.RequestID, Sequence: 2, Stage: edgeservice.SingleRequestStateCancelled, Terminal: &tc.disposition}) default: return ctrl.SubmitEnvelope(edgeservice.SingleRequestEnvelope{RequestID: req.RequestID, Sequence: 2, Stage: edgeservice.SingleRequestStateFailed, Terminal: &tc.disposition, Err: edgeservice.ErrSingleRequestFailed}) } }) svc := newAdmittedAnthropicSingleRequestService(t, executor, "ws-opaque-ref") srv := newAnthropicSingleRequestServer(t, svc) core, logs := observer.New(zap.InfoLevel) srv.logger = zap.New(core) w := httptest.NewRecorder() before := testutil.ToFloat64(singleRequestIngressTotal) serveAnthropicSingleRequest(t, srv, context.Background(), "/v1/messages", `{"model":"`+testSingleRequestModel+`","max_tokens":128,"messages":[{"role":"user","content":"run"}]}`, w) if got := testutil.ToFloat64(singleRequestIngressTotal) - before; got != 1 { t.Fatalf("ingress delta=%v, want 1", got) } if strings.Contains(w.Body.String(), privatePartial) { t.Fatalf("private partial output reached caller: %q", w.Body.String()) } entries := logs.FilterMessage(anthropicSingleRequestTerminalRejectionLogMessage).All() if tc.disposition.Kind == edgeservice.SingleRequestTerminalError { if len(entries) != 1 { t.Fatalf("terminal rejection logs=%d, want 1", len(entries)) } fields := entries[0].ContextMap() if fields["surface"] != "messages" || fields["terminal_kind"] != string(tc.disposition.Kind) || fields["terminal_error_class"] != string(tc.disposition.ErrorClass) || fields["http_status"] != int64(tc.wantStatus) { t.Fatalf("terminal rejection fields=%v", fields) } for _, forbidden := range []string{privatePartial, "ws-opaque-ref", "run"} { if strings.Contains(fmt.Sprintf("%v", fields), forbidden) { t.Fatalf("terminal rejection log leaked %q: %v", forbidden, fields) } } } else if len(entries) != 0 { t.Fatalf("terminal rejection logs=%d, want 0", len(entries)) } if tc.silent { if w.Body.Len() != 0 { t.Fatalf("cancel body=%q, want silent terminal", w.Body.String()) } return } if w.Code != tc.wantStatus { t.Fatalf("status=%d body=%q, want %d", w.Code, w.Body.String(), tc.wantStatus) } if tc.wantStop != "" { var response anthropicMessageResponse if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil { t.Fatalf("decode message terminal: %v", err) } if response.StopReason == nil || *response.StopReason != tc.wantStop { t.Fatalf("stop_reason=%v, want %q", response.StopReason, tc.wantStop) } if tc.disposition.Kind == edgeservice.SingleRequestTerminalLength && len(response.Content) != 0 { t.Fatalf("length content=%v, want empty", response.Content) } return } var response anthropicErrorResponse if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil { t.Fatalf("decode error terminal: %v", err) } if response.Error.Type != tc.wantType || response.Error.Message != tc.wantMessage { t.Fatalf("error=%+v, want %s/%q", response.Error, tc.wantType, tc.wantMessage) } }) } } func TestAnthropicSingleRequestLiveContextProviderCancellationBuffered(t *testing.T) { var providerCalls atomic.Int32 var providerContextDone atomic.Bool runner := &mockService{submit: func(ctx context.Context, _ edgeservice.ProviderPoolDispatchRequest) (*edgeservice.ProviderPoolDispatchResult, error) { if ctx.Err() != nil { providerContextDone.Store(true) } providerCalls.Add(1) return nil, context.Canceled }} executor := NewSingleRequestExecutor(runner) svc := newAdmittedAnthropicSingleRequestService(t, executor, "ws-opaque-ref") srv := newAnthropicSingleRequestServer(t, svc) w := httptest.NewRecorder() before := testutil.ToFloat64(singleRequestIngressTotal) body := `{"model":"` + testSingleRequestModel + `","max_tokens":128,"messages":[{"role":"user","content":"run"}]}` serveAnthropicSingleRequest(t, srv, context.Background(), "/v1/messages", body, w) if got := providerCalls.Load(); got != 1 { t.Fatalf("provider calls=%d, want 1", got) } if providerContextDone.Load() { t.Fatal("provider context was already done before the provider-owned cancellation") } if got := testutil.ToFloat64(singleRequestIngressTotal) - before; got != 1 { t.Fatalf("ingress delta=%v, want 1", got) } if w.Code != http.StatusBadGateway { t.Fatalf("status=%d body=%q, want 502", w.Code, w.Body.String()) } var response anthropicErrorResponse if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil { t.Fatalf("decode error terminal: %v", err) } if response.Error.Type != "api_error" || response.Error.Message != "single-request execution failed" { t.Fatalf("error=%+v, want sanitized provider api_error", response.Error) } for _, forbidden := range []string{"context canceled", "cancelled", "ws-opaque-ref", "plan-model", "provider-plan"} { if strings.Contains(w.Body.String(), forbidden) { t.Fatalf("buffered error leaked %q: %s", forbidden, w.Body.String()) } } } type anthropicInternalToolExecutor struct { results chan edgeservice.InternalWorkspaceToolResult continueCount atomic.Int32 } func newAnthropicInternalToolExecutor() *anthropicInternalToolExecutor { return &anthropicInternalToolExecutor{results: make(chan edgeservice.InternalWorkspaceToolResult, 2)} } func (e *anthropicInternalToolExecutor) ExecuteSingleRequest( ctx context.Context, req edgeservice.SingleRequestRequest, ctrl edgeservice.SingleRequestController, ) error { sequence := uint64(1) if err := ctrl.SubmitEnvelope(edgeservice.SingleRequestEnvelope{RequestID: req.RequestID, Sequence: sequence, Stage: edgeservice.SingleRequestStatePlanning}); err != nil { return err } calls := []*edgeservice.InternalWorkspaceToolCall{ { RequestID: req.RequestID, StageID: "plan", ToolCallID: "tool-read", Name: edgeservice.InternalWorkspaceToolRead, Arguments: json.RawMessage(`{"relative_path":"README.md"}`), }, { RequestID: req.RequestID, StageID: "plan", ToolCallID: "tool-write", Name: edgeservice.InternalWorkspaceToolWrite, Arguments: json.RawMessage(`{"relative_path":"result.txt","content":"PRIVATE_INTERNAL_ARGUMENT_SENTINEL"}`), }, } for _, call := range calls { sequence++ if err := ctrl.SubmitEnvelope(edgeservice.SingleRequestEnvelope{ RequestID: req.RequestID, Sequence: sequence, Stage: edgeservice.SingleRequestStateInternalTool, SavedStage: edgeservice.SingleRequestStatePlanning, ToolCall: call, }); err != nil { return err } select { case result := <-e.results: if result.RequestID != req.RequestID || result.StageID != "plan" || result.ToolCallID != call.ToolCallID { return errors.New("internal tool result identity mismatch") } case <-ctx.Done(): return ctx.Err() } sequence++ if err := ctrl.SubmitEnvelope(edgeservice.SingleRequestEnvelope{ RequestID: req.RequestID, Sequence: sequence, Stage: edgeservice.SingleRequestStatePlanning, SavedStage: edgeservice.SingleRequestStatePlanning, }); err != nil { return err } } for _, stage := range []edgeservice.SingleRequestState{ edgeservice.SingleRequestStateWorking, edgeservice.SingleRequestStateReviewing, edgeservice.SingleRequestStateFinalizing, } { sequence++ envelope := edgeservice.SingleRequestEnvelope{RequestID: req.RequestID, Sequence: sequence, Stage: stage} if stage == edgeservice.SingleRequestStateFinalizing { envelope.Result = &edgeservice.SingleRequestResult{Output: "workspace task completed privately"} } if err := ctrl.SubmitEnvelope(envelope); err != nil { return err } } return nil } func (e *anthropicInternalToolExecutor) ContinueInternalTool(_ context.Context, result edgeservice.InternalWorkspaceToolResult) error { e.continueCount.Add(1) e.results <- result.Clone() return nil } func newAnthropicInternalToolService( t *testing.T, executor *anthropicInternalToolExecutor, ) (*edgeservice.Service, *toki.TcpClient) { t.Helper() edgeConn, nodeConn := net.Pipe() edgeClient := toki.NewTcpClient(edgeConn, 0, 0, toki.ParserMap{ toki.TypeNameOf(&iop.WorkspaceOpenResponse{}): parseAnthropicWorkspaceMessage(&iop.WorkspaceOpenResponse{}), toki.TypeNameOf(&iop.WorkspaceToolResponse{}): parseAnthropicWorkspaceMessage(&iop.WorkspaceToolResponse{}), toki.TypeNameOf(&iop.WorkspaceCleanupResponse{}): parseAnthropicWorkspaceMessage(&iop.WorkspaceCleanupResponse{}), }) nodeClient := toki.NewTcpClient(nodeConn, 0, 0, toki.ParserMap{ toki.TypeNameOf(&iop.WorkspaceOpenRequest{}): parseAnthropicWorkspaceMessage(&iop.WorkspaceOpenRequest{}), toki.TypeNameOf(&iop.WorkspaceToolRequest{}): parseAnthropicWorkspaceMessage(&iop.WorkspaceToolRequest{}), toki.TypeNameOf(&iop.WorkspaceCleanupRequest{}): parseAnthropicWorkspaceMessage(&iop.WorkspaceCleanupRequest{}), }) t.Cleanup(func() { _ = edgeClient.Close() _ = nodeClient.Close() }) registry := edgenode.NewRegistry() registry.Register(&edgenode.NodeEntry{NodeID: "workspace-node", Alias: "workspace", Client: edgeClient}) store := edgenode.NewNodeStore() store.Add(&edgenode.NodeRecord{ ID: "workspace-node", Alias: "workspace", Token: "workspace-node-token", Workspaces: []config.WorkspaceDefinition{{ Ref: "ws-opaque-ref", Platform: "darwin", Root: "/Users/operator/project", Operations: []config.WorkspaceOperation{config.WorkspaceOpRead, config.WorkspaceOpWrite}, MaxReadBytes: 4096, MaxWriteBytes: 4096, }}, }) service := edgeservice.New(registry, nil) service.SetNodeStore(store) service.SetSingleRequestExecutor(executor) return service, nodeClient } func parseAnthropicWorkspaceMessage(template proto.Message) func([]byte) (proto.Message, error) { return func(payload []byte) (proto.Message, error) { message := template.ProtoReflect().Type().New().Interface() return message, proto.Unmarshal(payload, message) } } func TestAnthropicSingleRequestInternalToolsStayPrivate(t *testing.T) { executor := newAnthropicInternalToolExecutor() service, node := newAnthropicInternalToolService(t, executor) var openCount atomic.Int32 var toolCount atomic.Int32 toolOrder := make(chan string, 2) var cleanupCount atomic.Int32 toki.AddRequestListenerTyped[*iop.WorkspaceOpenRequest, *iop.WorkspaceOpenResponse](&node.Communicator, func(req *iop.WorkspaceOpenRequest) (*iop.WorkspaceOpenResponse, error) { openCount.Add(1) return &iop.WorkspaceOpenResponse{RequestId: req.GetRequestId(), WorkspaceRef: req.GetWorkspaceRef(), Status: iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS}, nil }) toki.AddRequestListenerTyped[*iop.WorkspaceToolRequest, *iop.WorkspaceToolResponse](&node.Communicator, func(req *iop.WorkspaceToolRequest) (*iop.WorkspaceToolResponse, error) { toolCount.Add(1) toolOrder <- req.GetToolCallId() response := &iop.WorkspaceToolResponse{ RequestId: req.GetRequestId(), StageId: req.GetStageId(), ToolCallId: req.GetToolCallId(), Status: iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS, } if req.GetOperation() == iop.WorkspaceOperation_WORKSPACE_OPERATION_READ { response.Content = []byte("private read result") } return response, nil }) toki.AddRequestListenerTyped[*iop.WorkspaceCleanupRequest, *iop.WorkspaceCleanupResponse](&node.Communicator, func(req *iop.WorkspaceCleanupRequest) (*iop.WorkspaceCleanupResponse, error) { cleanupCount.Add(1) return &iop.WorkspaceCleanupResponse{ RequestId: req.GetRequestId(), Status: iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS, }, nil }) srv := newAnthropicSingleRequestServer(t, service) var httpRequests atomic.Int32 httpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { httpRequests.Add(1) srv.routes().ServeHTTP(w, r) })) defer httpServer.Close() before := testutil.ToFloat64(singleRequestIngressTotal) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() body := `{"model":"` + testSingleRequestModel + `","max_tokens":128,"messages":[{"role":"user","content":"complete the task"}]}` request := newAnthropicSingleRequestHTTPReq(t, ctx, httpServer.URL, "/v1/messages", body) response, err := httpServer.Client().Do(request) if err != nil { t.Fatalf("POST /v1/messages: %v", err) } defer response.Body.Close() payload, err := io.ReadAll(response.Body) if err != nil { t.Fatal(err) } if response.StatusCode != http.StatusOK { t.Fatalf("status=%d body=%s", response.StatusCode, payload) } var terminal anthropicMessageResponse decoder := json.NewDecoder(strings.NewReader(string(payload))) if err := decoder.Decode(&terminal); err != nil { t.Fatalf("decode terminal: %v", err) } var extra json.RawMessage if err := decoder.Decode(&extra); err != io.EOF { t.Fatalf("terminal had trailing output: %v %s", err, extra) } if len(terminal.Content) != 1 || terminal.Content[0]["text"] != "workspace task completed privately" { t.Fatalf("terminal content = %+v", terminal.Content) } for _, private := range []string{ "tool_use", "tool_result", edgeservice.InternalWorkspaceToolRead, edgeservice.InternalWorkspaceToolWrite, "PRIVATE_INTERNAL_ARGUMENT_SENTINEL", "private read result", } { if strings.Contains(string(payload), private) { t.Fatalf("public terminal leaked %q: %s", private, payload) } } if httpRequests.Load() != 1 || testutil.ToFloat64(singleRequestIngressTotal)-before != 1 { t.Fatalf("HTTP requests=%d ingress delta=%v, want 1/1", httpRequests.Load(), testutil.ToFloat64(singleRequestIngressTotal)-before) } if openCount.Load() != 1 || toolCount.Load() != 2 || cleanupCount.Load() != 1 || executor.continueCount.Load() != 2 { t.Fatalf("open=%d tools=%d cleanup=%d continuations=%d, want 1/2/1/2", openCount.Load(), toolCount.Load(), cleanupCount.Load(), executor.continueCount.Load()) } for index, want := range []string{"tool-read", "tool-write"} { if got := <-toolOrder; got != want { t.Fatalf("tool order[%d]=%q, want %q", index, got, want) } } } type singleRequestMetricKey struct { eventClass string stage string operation string outcome string errorClass string } func singleRequestMetricKeyFromLabels(labels []*dto.LabelPair) (singleRequestMetricKey, error) { var key singleRequestMetricKey seen := make(map[string]bool) for _, lp := range labels { name := lp.GetName() if seen[name] { return singleRequestMetricKey{}, fmt.Errorf("duplicate metric label %q", name) } seen[name] = true switch name { case "event_class": key.eventClass = lp.GetValue() case "stage": key.stage = lp.GetValue() case "operation": key.operation = lp.GetValue() case "outcome": key.outcome = lp.GetValue() case "error_class": key.errorClass = lp.GetValue() default: return singleRequestMetricKey{}, fmt.Errorf("unexpected metric label %q", name) } } expectedLabels := []string{"event_class", "stage", "operation", "outcome", "error_class"} for _, expected := range expectedLabels { if !seen[expected] { return singleRequestMetricKey{}, fmt.Errorf("missing metric label %q", expected) } } return key, nil } func isValidSingleRequestCorrelationID(corr string) bool { if strings.HasPrefix(corr, "sr-fallback-") { rest := corr[len("sr-fallback-"):] if len(rest) == 0 || len(rest) > 32 { return false } for _, r := range rest { if !((r >= '0' && r <= '9') || (r >= 'a' && r <= 'z')) { return false } } return true } if strings.HasPrefix(corr, "sr-") { rest := corr[len("sr-"):] if len(rest) != 32 { return false } for _, r := range rest { if !((r >= '0' && r <= '9') || (r >= 'a' && r <= 'f')) { return false } } return true } return false } func zapFieldTypeName(t zapcore.FieldType) string { switch t { case zapcore.StringType: return "StringType" case zapcore.Int64Type: return "Int64Type" case zapcore.Int32Type: return "Int32Type" case zapcore.Float64Type: return "Float64Type" case zapcore.BoolType: return "BoolType" default: return fmt.Sprintf("FieldType(%d)", t) } } func singleRequestLogKey(fields []zapcore.Field) (singleRequestMetricKey, string, error) { if len(fields) != 9 { return singleRequestMetricKey{}, "", fmt.Errorf("expected 9 context fields, got %d", len(fields)) } expectedTypes := map[string]zapcore.FieldType{ "correlation": zapcore.StringType, "event_class": zapcore.StringType, "stage": zapcore.StringType, "operation": zapcore.StringType, "outcome": zapcore.StringType, "error_class": zapcore.StringType, "duration_ms": zapcore.Int64Type, "tool_count": zapcore.Int64Type, "has_result": zapcore.BoolType, } seen := make(map[string]bool, len(fields)) stringVals := make(map[string]string) for _, f := range fields { if seen[f.Key] { return singleRequestMetricKey{}, "", fmt.Errorf("duplicate context key %q", f.Key) } wantType, ok := expectedTypes[f.Key] if !ok { return singleRequestMetricKey{}, "", fmt.Errorf("unexpected context key %q", f.Key) } if f.Type != wantType { return singleRequestMetricKey{}, "", fmt.Errorf("key %q has Zap type %s, want %s", f.Key, zapFieldTypeName(f.Type), zapFieldTypeName(wantType)) } seen[f.Key] = true if wantType == zapcore.StringType { stringVals[f.Key] = f.String } } for k := range expectedTypes { if !seen[k] { return singleRequestMetricKey{}, "", fmt.Errorf("missing context key %q", k) } } corrVal := stringVals["correlation"] if !isValidSingleRequestCorrelationID(corrVal) { return singleRequestMetricKey{}, "", fmt.Errorf("invalid correlation format %q", corrVal) } key := singleRequestMetricKey{ eventClass: stringVals["event_class"], stage: stringVals["stage"], operation: stringVals["operation"], outcome: stringVals["outcome"], errorClass: stringVals["error_class"], } return key, corrVal, nil } func snapshotSingleRequestMetrics(gatherer prometheus.Gatherer) (map[singleRequestMetricKey]float64, map[singleRequestMetricKey]uint64, error) { var families []*dto.MetricFamily var err error families, err = gatherer.Gather() if err != nil { return nil, nil, err } counters := make(map[singleRequestMetricKey]float64) histograms := make(map[singleRequestMetricKey]uint64) for _, family := range families { switch family.GetName() { case "iop_edge_single_request_lifecycle_total": for _, m := range family.GetMetric() { key, err := singleRequestMetricKeyFromLabels(m.GetLabel()) if err != nil { return nil, nil, fmt.Errorf("family %s metric key error: %w", family.GetName(), err) } counters[key] = m.GetCounter().GetValue() } case "iop_edge_single_request_duration_seconds": for _, m := range family.GetMetric() { key, err := singleRequestMetricKeyFromLabels(m.GetLabel()) if err != nil { return nil, nil, fmt.Errorf("family %s metric key error: %w", family.GetName(), err) } histograms[key] = m.GetHistogram().GetSampleCount() } } } return counters, histograms, nil } // TestAnthropicSingleRequestObservation links ingress, request-total, terminal, // stage/tool/cleanup counts, and raw-free correlation for a real marked POST // that exercises deterministic internal tools. It asserts the single-request // lifecycle produces exactly one accepted ingress, one executor call, one // terminal acknowledgement, the expected stage/tool/cleanup deltas, and a // public terminal that never carries internal tool protocol or raw values. // External Claude timing evidence on an approved IOP Node is explicitly deferred to claude-smoke. func TestAnthropicSingleRequestObservation(t *testing.T) { executor := newAnthropicInternalToolExecutor() service, node := newAnthropicInternalToolService(t, executor) var openCount atomic.Int32 var toolCount atomic.Int32 var cleanupCount atomic.Int32 toki.AddRequestListenerTyped[*iop.WorkspaceOpenRequest, *iop.WorkspaceOpenResponse](&node.Communicator, func(req *iop.WorkspaceOpenRequest) (*iop.WorkspaceOpenResponse, error) { openCount.Add(1) return &iop.WorkspaceOpenResponse{RequestId: req.GetRequestId(), WorkspaceRef: req.GetWorkspaceRef(), Status: iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS}, nil }) toki.AddRequestListenerTyped[*iop.WorkspaceToolRequest, *iop.WorkspaceToolResponse](&node.Communicator, func(req *iop.WorkspaceToolRequest) (*iop.WorkspaceToolResponse, error) { toolCount.Add(1) response := &iop.WorkspaceToolResponse{ RequestId: req.GetRequestId(), StageId: req.GetStageId(), ToolCallId: req.GetToolCallId(), Status: iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS, } return response, nil }) toki.AddRequestListenerTyped[*iop.WorkspaceCleanupRequest, *iop.WorkspaceCleanupResponse](&node.Communicator, func(req *iop.WorkspaceCleanupRequest) (*iop.WorkspaceCleanupResponse, error) { cleanupCount.Add(1) return &iop.WorkspaceCleanupResponse{ RequestId: req.GetRequestId(), Status: iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS, }, nil }) core, logs := observer.New(zap.InfoLevel) obsLogger := zap.New(core) lifecycleRegistry := prometheus.NewRegistry() service.SetSingleRequestObservationLoggerForTesting(lifecycleRegistry, obsLogger) srv := newAnthropicSingleRequestServer(t, service) httpServer := httptest.NewServer(srv.routes()) defer httpServer.Close() beforeIngress := testutil.ToFloat64(singleRequestIngressTotal) beforeCounters, beforeHistograms, err := snapshotSingleRequestMetrics(lifecycleRegistry) if err != nil { t.Fatalf("snapshot initial metrics: %v", err) } ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() body := `{"model":"` + testSingleRequestModel + `","max_tokens":128,"messages":[{"role":"user","content":"complete the task"}]}` request := newAnthropicSingleRequestHTTPReq(t, ctx, httpServer.URL, "/v1/messages", body) response, err := httpServer.Client().Do(request) if err != nil { t.Fatalf("POST /v1/messages: %v", err) } defer response.Body.Close() payload, err := io.ReadAll(response.Body) if err != nil { t.Fatal(err) } if response.StatusCode != http.StatusOK { t.Fatalf("status=%d body=%s", response.StatusCode, payload) } var terminal anthropicMessageResponse decoder := json.NewDecoder(strings.NewReader(string(payload))) if err := decoder.Decode(&terminal); err != nil { t.Fatalf("decode terminal: %v", err) } var extra json.RawMessage if err := decoder.Decode(&extra); err != io.EOF { t.Fatalf("terminal had trailing output: %v %s", err, extra) } if terminal.Model != testSingleRequestModel || terminal.Type != "message" || terminal.Role != "assistant" { t.Fatalf("public terminal identity mismatch: %+v", terminal) } if terminal.StopReason == nil || *terminal.StopReason != "end_turn" { t.Fatalf("stop_reason=%v, want end_turn", terminal.StopReason) } if len(terminal.Content) != 1 || terminal.Content[0]["type"] != "text" { t.Fatalf("terminal content=%+v, want one sanitized text block", terminal.Content) } encoded, err := json.Marshal(terminal) if err != nil { t.Fatal(err) } for _, privateValue := range []string{ "tool_use", "tool_result", edgeservice.InternalWorkspaceToolRead, edgeservice.InternalWorkspaceToolWrite, "PRIVATE_INTERNAL_ARGUMENT_SENTINEL", "private read result", "ws-opaque-ref", "plan-model", "provider-plan", "slot-plan", } { if strings.Contains(string(encoded), privateValue) { t.Fatalf("terminal leaked %q: %s", privateValue, encoded) } } if got := testutil.ToFloat64(singleRequestIngressTotal) - beforeIngress; got != 1 { t.Fatalf("single-request ingress counter delta=%v, want 1", got) } if got := executor.continueCount.Load(); got != 2 { t.Fatalf("executor continuations=%d, want 2 (one per internal tool)", got) } if openCount.Load() != 1 { t.Fatalf("workspace open count=%d, want 1", openCount.Load()) } if toolCount.Load() != 2 { t.Fatalf("internal tool count=%d, want 2", toolCount.Load()) } if cleanupCount.Load() != 1 { t.Fatalf("workspace cleanup count=%d, want 1", cleanupCount.Load()) } afterCounters, afterHistograms, err := snapshotSingleRequestMetrics(lifecycleRegistry) if err != nil { t.Fatalf("snapshot final metrics: %v", err) } wantDeltas := map[singleRequestMetricKey]float64{ {eventClass: "request", stage: "none", operation: "total", outcome: "success", errorClass: "none"}: 1, {eventClass: "stage", stage: "plan", operation: "plan", outcome: "success", errorClass: "none"}: 1, {eventClass: "stage", stage: "work", operation: "work", outcome: "success", errorClass: "none"}: 1, {eventClass: "stage", stage: "review", operation: "review", outcome: "success", errorClass: "none"}: 1, {eventClass: "tool", stage: "none", operation: "tool", outcome: "success", errorClass: "none"}: 2, {eventClass: "cleanup", stage: "none", operation: "cleanup", outcome: "success", errorClass: "none"}: 1, {eventClass: "terminal", stage: "none", operation: "terminal", outcome: "success", errorClass: "none"}: 1, } for key, wantDelta := range wantDeltas { gotCounterDelta := afterCounters[key] - beforeCounters[key] if gotCounterDelta != wantDelta { t.Fatalf("lifecycle metric counter delta for %+v = %v, want %v", key, gotCounterDelta, wantDelta) } gotHistDelta := afterHistograms[key] - beforeHistograms[key] if float64(gotHistDelta) != wantDelta { t.Fatalf("lifecycle metric duration delta for %+v = %v, want %v", key, gotHistDelta, wantDelta) } } for key, afterVal := range afterCounters { delta := afterVal - beforeCounters[key] if delta > 0 { if _, expected := wantDeltas[key]; !expected { t.Fatalf("unexpected lifecycle metric delta for key %+v: %v", key, delta) } } } entries := logs.All() if len(entries) != 8 { t.Fatalf("captured observation logs count = %d, want 8", len(entries)) } logCounts := make(map[singleRequestMetricKey]float64) var requestCorrelation string for i, entry := range entries { if entry.Message != "edge_single_request_observation" { t.Fatalf("log[%d] message = %q, want edge_single_request_observation", i, entry.Message) } key, corrVal, err := singleRequestLogKey(entry.Context) if err != nil { t.Fatalf("log[%d] schema: %v", i, err) } if i == 0 { requestCorrelation = corrVal } else if corrVal != requestCorrelation { t.Fatalf("log[%d] correlation = %q, want shared correlation %q", i, corrVal, requestCorrelation) } logCounts[key]++ rawLog := fmt.Sprintf("%+v", entry.ContextMap()) for _, privateValue := range []string{ edgeservice.InternalWorkspaceToolRead, edgeservice.InternalWorkspaceToolWrite, "README.md", "result.txt", "PRIVATE_INTERNAL_ARGUMENT_SENTINEL", "private read result", "ws-opaque-ref", "complete the task", "workspace task completed privately", } { if strings.Contains(rawLog, privateValue) { t.Fatalf("log[%d] leaked private content %q: %s", i, privateValue, rawLog) } } } if len(logCounts) != len(wantDeltas) { t.Fatalf("captured log unique tuple count = %d, want %d", len(logCounts), len(wantDeltas)) } for key, wantCount := range wantDeltas { if got := logCounts[key]; got != wantCount { t.Fatalf("captured log count for tuple %+v = %v, want %v", key, got, wantCount) } } families, err := prometheus.DefaultGatherer.Gather() if err != nil { t.Fatalf("gather metrics: %v", err) } foundMetric := false for _, family := range families { if family.GetName() != "iop_anthropic_single_request_ingress_total" { continue } foundMetric = true for _, metric := range family.Metric { if len(metric.Label) != 0 { t.Fatalf("single-request ingress metric has request-derived labels: %+v", metric.Label) } } } if !foundMetric { t.Fatal("registered single-request ingress metric was not gathered") } } func TestAnthropicSingleRequestUnavailableFailsClosed(t *testing.T) { fake := &providerFakeRunService{poolDispatchPath: string(edgeservice.ProviderPoolPathTunnel)} srv := newAnthropicSingleRequestServer(t, fake) before := testutil.ToFloat64(singleRequestIngressTotal) w := httptest.NewRecorder() body := `{"model":"` + testSingleRequestModel + `","max_tokens":32,"messages":[{"role":"user","content":"hello"}]}` serveAnthropicSingleRequest(t, srv, context.Background(), "/v1/messages", body, w) if w.Code != http.StatusServiceUnavailable { t.Fatalf("status=%d body=%s", w.Code, w.Body.String()) } if !strings.Contains(w.Body.String(), "single-request execution is unavailable") { t.Fatalf("unexpected unavailable body: %s", w.Body.String()) } if got := fake.poolSubmitCountSnapshot(); got != 0 { t.Fatalf("marked request fell back to provider pool: submissions=%d", got) } if got := testutil.ToFloat64(singleRequestIngressTotal) - before; got != 0 { t.Fatalf("unavailable capability changed accepted-ingress counter by %v", got) } } func TestAnthropicSingleRequestExecutorFailureIsSanitized(t *testing.T) { const privateFailure = "PRIVATE_PROVIDER_ROUTE_CREDENTIAL_FAILURE" executor := anthropicSingleRequestExecutorFunc(func( context.Context, edgeservice.SingleRequestRequest, edgeservice.SingleRequestController, ) error { return errors.New(privateFailure) }) svc := newAdmittedAnthropicSingleRequestService(t, executor, "ws-opaque-ref") srv := newAnthropicSingleRequestServer(t, svc) w := httptest.NewRecorder() body := `{"model":"` + testSingleRequestModel + `","max_tokens":32,"messages":[{"role":"user","content":"hello"}]}` serveAnthropicSingleRequest(t, srv, context.Background(), "/v1/messages", body, w) if w.Code != http.StatusBadGateway { t.Fatalf("status=%d body=%s", w.Code, w.Body.String()) } if strings.Contains(w.Body.String(), privateFailure) || !strings.Contains(w.Body.String(), "single-request execution failed") { t.Fatalf("executor failure was not sanitized: %s", w.Body.String()) } } type singleRequestFailingWriter struct { header http.Header status int } func (w *singleRequestFailingWriter) Header() http.Header { if w.header == nil { w.header = make(http.Header) } return w.header } func (w *singleRequestFailingWriter) WriteHeader(status int) { w.status = status } func (w *singleRequestFailingWriter) Write([]byte) (int, error) { return 0, errors.New("test response write failure") } func TestAnthropicSingleRequestWriteFailureRejectsAcknowledgement(t *testing.T) { controllerCh := make(chan edgeservice.SingleRequestController, 1) executor := anthropicSingleRequestExecutorFunc(func( _ context.Context, req edgeservice.SingleRequestRequest, ctrl edgeservice.SingleRequestController, ) error { if err := submitAnthropicSingleRequestLifecycle(req, ctrl, "safe final"); err != nil { return err } controllerCh <- ctrl return nil }) svc := newAdmittedAnthropicSingleRequestService(t, executor, "ws-opaque-ref") srv := newAnthropicSingleRequestServer(t, svc) w := &singleRequestFailingWriter{} body := `{"model":"` + testSingleRequestModel + `","max_tokens":32,"messages":[{"role":"user","content":"hello"}]}` serveAnthropicSingleRequest(t, srv, context.Background(), "/v1/messages", body, w) if w.status != http.StatusOK { t.Fatalf("write status=%d, want attempted 200 terminal", w.status) } if got := (<-controllerCh).State(); got != edgeservice.SingleRequestStateFailed { t.Fatalf("write-failure acknowledgement state=%s, want failed", got) } } func TestAnthropicSingleRequestCallerCancellationCancelsExecution(t *testing.T) { controllerCh := make(chan edgeservice.SingleRequestController, 1) executor := anthropicSingleRequestExecutorFunc(func( ctx context.Context, _ edgeservice.SingleRequestRequest, ctrl edgeservice.SingleRequestController, ) error { controllerCh <- ctrl <-ctx.Done() return ctx.Err() }) svc := newAdmittedAnthropicSingleRequestService(t, executor, "ws-opaque-ref") srv := newAnthropicSingleRequestServer(t, svc) ctx, cancel := context.WithCancel(context.Background()) w := httptest.NewRecorder() done := make(chan struct{}) body := `{"model":"` + testSingleRequestModel + `","max_tokens":32,"messages":[{"role":"user","content":"hello"}]}` go func() { defer close(done) serveAnthropicSingleRequest(t, srv, ctx, "/v1/messages", body, w) }() controller := <-controllerCh cancel() select { case <-done: case <-time.After(2 * time.Second): t.Fatal("handler did not return after caller cancellation") } if got := controller.State(); got != edgeservice.SingleRequestStateCancelled { t.Fatalf("caller-cancel state=%s, want cancelled", got) } if w.Body.Len() != 0 { t.Fatalf("caller cancellation wrote a terminal after disconnect: %s", w.Body.String()) } } func TestAnthropicSingleRequestCountTokensBypassesExecution(t *testing.T) { fake := &providerFakeRunService{poolDispatchPath: string(edgeservice.ProviderPoolPathTunnel)} srv := newAnthropicSingleRequestServer(t, fake) before := testutil.ToFloat64(singleRequestIngressTotal) w := httptest.NewRecorder() body := `{"model":"` + testSingleRequestModel + `","messages":[{"role":"user","content":"count this"}]}` serveAnthropicSingleRequest(t, srv, context.Background(), "/v1/messages/count_tokens", body, w) if w.Code != http.StatusOK || !strings.Contains(w.Body.String(), `"input_tokens"`) { t.Fatalf("count-tokens status=%d body=%s", w.Code, w.Body.String()) } if got := fake.poolSubmitCountSnapshot(); got != 0 { t.Fatalf("local count-tokens used provider pool: submissions=%d", got) } if got := testutil.ToFloat64(singleRequestIngressTotal) - before; got != 0 { t.Fatalf("count-tokens changed Messages ingress counter by %v", got) } } func TestSingleRequestLogSchemaRejectsDrift(t *testing.T) { validFields := func() []zapcore.Field { return []zapcore.Field{ zap.String("correlation", "sr-0123456789abcdef0123456789abcdef"), zap.String("event_class", "request"), zap.String("stage", "none"), zap.String("operation", "total"), zap.String("outcome", "success"), zap.String("error_class", "none"), zap.Int64("duration_ms", 15), zap.Int("tool_count", 0), zap.Bool("has_result", false), } } key, corr, err := singleRequestLogKey(validFields()) if err != nil { t.Fatalf("valid baseline fields rejected: %v", err) } if corr != "sr-0123456789abcdef0123456789abcdef" { t.Fatalf("correlation = %q, want sr-0123456789abcdef0123456789abcdef", corr) } wantKey := singleRequestMetricKey{ eventClass: "request", stage: "none", operation: "total", outcome: "success", errorClass: "none", } if key != wantKey { t.Fatalf("key = %+v, want %+v", key, wantKey) } fallbackFields := validFields() fallbackFields[0] = zap.String("correlation", "sr-fallback-1a2b3c") if _, _, err := singleRequestLogKey(fallbackFields); err != nil { t.Fatalf("valid fallback correlation rejected: %v", err) } tests := []struct { name string mutate func([]zapcore.Field) []zapcore.Field wantErr string }{ { name: "duplicate_key", mutate: func(f []zapcore.Field) []zapcore.Field { res := append([]zapcore.Field(nil), f...) res[1] = zap.String("correlation", "sr-0123456789abcdef0123456789abcdef") return res }, wantErr: "duplicate context key \"correlation\"", }, { name: "missing_key", mutate: func(f []zapcore.Field) []zapcore.Field { return f[:len(f)-1] }, wantErr: "expected 9 context fields, got 8", }, { name: "unknown_key", mutate: func(f []zapcore.Field) []zapcore.Field { res := append([]zapcore.Field(nil), f...) res[0] = zap.String("unexpected_key", "sr-0123456789abcdef0123456789abcdef") return res }, wantErr: "unexpected context key \"unexpected_key\"", }, { name: "wrong_numeric_type_float64", mutate: func(f []zapcore.Field) []zapcore.Field { res := append([]zapcore.Field(nil), f...) res[6] = zap.Float64("duration_ms", 15.0) return res }, wantErr: "key \"duration_ms\" has Zap type Float64Type, want Int64Type", }, { name: "wrong_numeric_type_int32", mutate: func(f []zapcore.Field) []zapcore.Field { res := append([]zapcore.Field(nil), f...) res[7] = zap.Int32("tool_count", 0) return res }, wantErr: "key \"tool_count\" has Zap type Int32Type, want Int64Type", }, { name: "wrong_string_type", mutate: func(f []zapcore.Field) []zapcore.Field { res := append([]zapcore.Field(nil), f...) res[2] = zap.Int64("stage", 1) return res }, wantErr: "key \"stage\" has Zap type Int64Type, want StringType", }, { name: "wrong_bool_type", mutate: func(f []zapcore.Field) []zapcore.Field { res := append([]zapcore.Field(nil), f...) res[8] = zap.String("has_result", "false") return res }, wantErr: "key \"has_result\" has Zap type StringType, want BoolType", }, { name: "constant_correlation", mutate: func(f []zapcore.Field) []zapcore.Field { res := append([]zapcore.Field(nil), f...) res[0] = zap.String("correlation", "constant-correlation-id") return res }, wantErr: "invalid correlation format \"constant-correlation-id\"", }, { name: "short_hex_correlation", mutate: func(f []zapcore.Field) []zapcore.Field { res := append([]zapcore.Field(nil), f...) res[0] = zap.String("correlation", "sr-12345") return res }, wantErr: "invalid correlation format \"sr-12345\"", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mutated := tt.mutate(validFields()) _, _, err := singleRequestLogKey(mutated) if err == nil { t.Fatalf("expected error containing %q, got nil", tt.wantErr) } if !strings.Contains(err.Error(), tt.wantErr) { t.Fatalf("err = %q, want error containing %q", err.Error(), tt.wantErr) } }) } }