Skip to content

test+fix: address principal-engineer review findings (Phases 0-4)#618

Closed
lakhansamani wants to merge 1 commit into
feat/mcp-serverfrom
feat/test-coverage
Closed

test+fix: address principal-engineer review findings (Phases 0-4)#618
lakhansamani wants to merge 1 commit into
feat/mcp-serverfrom
feat/test-coverage

Conversation

@lakhansamani
Copy link
Copy Markdown
Contributor

Stacked on top of #617 (which is stacked on #616#615#614). Review and merge after Phase 4.

Summary

Adds the missing integration/e2e test coverage flagged across reviews of #614 / #615 / #616 / #617, and fixes the blocking bugs those reviews surfaced. Test additions are spread across every layer the PR stack introduces; fixes are deliberately scoped to issues that would have hit production on the first deploy.

New tests (8 files, ~50 sub-cases)

File Coverage
`internal/parsers/url_test.go` `GetHostFromRequest` priority + spoof rejection; `GetAppURLFromRequest`
`internal/cookie/cookie_test.go` `BuildSessionCookies`/`BuildMfaSessionCookies` shape, MaxAge, Secure, HttpOnly, SameSite; `ParseSameSite`
`internal/service/sideeffects_test.go` `MetaFromGin`/`ApplyToGin` nil-safety + cookie round-trip
`internal/grpcsrv/interceptors/interceptors_test.go` Recovery (panic→Internal), Logging (per-code level), Validate (protovalidate)
`internal/grpcsrv/transport/grpc_metadata_test.go` `MetaFromGRPC` host/IP/UA/auth/cookies + `:authority` fallback
`internal/mcp/schema_test.go` Flat scalars, nested message, cycle-safety regression test for AppData→Struct→Value
`internal/integration_tests/grpc_surface_test.go` All 18 stub RPCs verified to return `codes.Unimplemented` + gRPC health endpoint
`internal/integration_tests/rest_openapi_test.go` `/openapi.json` serves valid swagger 2.0
`internal/integration_tests/mcp_stubs_test.go` MCP stubbed-tool call returns `CallToolResult{IsError:true}`

Blocking fixes from review

# Where Fix
#616-1 `cmd/root.go` --grpc-port default 8081 collided with --metrics-port. Moved gRPC to 9091. Added triple-port collision check (HTTP/metrics/gRPC); fails fast at startup.
#616-2 `internal/grpcsrv/transport/grpc_metadata.go` `MetaFromGRPC` now extracts cookies from `grpcgateway-cookie` / `cookie` metadata. Without this fix, every authenticated flow would break the moment SessionService stubs became real handlers.
#616-3 same file `ApplyToGRPC` now emits all Set-Cookie metadata entries (was dropping all but first).
#616-4 `internal/server/http_routes.go` + new `gen/openapi/openapi.go` `/openapi.json` was reading via relative path (broke in Docker/tests). Now embedded via `//go:embed`.
#617-1 `internal/mcp/schema.go` `schemaForMessage` tracks visited descriptors. Without this, exposing any tool whose request contained `google.protobuf.Value` (e.g. AppData→Struct→Value→repeated Value) would stack-overflow at boot.
#617-2 `internal/mcp/server.go` Tool execution errors now surface as `CallToolResult{IsError:true}` (MCP-spec way) instead of opaque JSON-RPC failures.
#617-3 `internal/mcp/scanner.go` Removed unused `descriptorOptionsCarrier` dead-code struct + always-failing type assertion.

Deliberately deferred (tracked but not in this PR)

  • `--grpc-tls-cert/-key/-insecure` placeholders — flagged by reviewer; deferred to a focused TLS PR alongside the metrics-listener TLS work.
  • Secrets in REST path (`DELETE /v1/refresh-tokens/{token}` etc.) — flagged by reviewer; moving to body-borne tokens is a proto-design change worth its own PR + discussion.
  • MCP auth metadata propagation — flagged by reviewer; today's MCP-exposed tools are `GetMeta` (no auth) + 3 stubs. Real wiring lands when the stubs become real handlers.

Test plan

  • Full `go test ./...` green (17 packages, 69s integration suite)
  • `go build ./...` clean
  • CI green on this stacked PR

🤖 Generated with Claude Code

Adds the missing integration/e2e test coverage flagged across reviews of
#614 / #615 / #616 / #617, and fixes the blocking bugs those reviews
surfaced. Test additions are spread across every layer the PR stack
introduces; fixes are deliberately scoped to issues that would have hit
production on the first deploy.

NEW TESTS

internal/parsers/url_test.go
  - TestGetHostFromRequest: header priority + spoof rejection
  - TestGetAppURLFromRequest

internal/cookie/cookie_test.go
  - TestBuildSessionCookies: 3 hostname scenarios, validates domain-scoped
    cookie picks up the apex, MaxAge/Secure/HttpOnly/SameSite all preserved
  - TestBuildMfaSessionCookies + insecure-Lax-SameSite variant
  - TestParseSameSite

internal/service/sideeffects_test.go
  - MetaFromGin / ApplyToGin nil-safety + cookie round-trip
  - ResponseSideEffects.AddCookie nil tolerance

internal/grpcsrv/interceptors/interceptors_test.go
  - Recovery turns panic into codes.Internal; stack stays server-side
  - Recovery passes normal errors through unchanged
  - Logging emits info/warn/error at the right thresholds per gRPC code
  - Validate rejects bad requests (protovalidate enforces email format)
  - Validate allows valid requests and tolerates non-proto request types

internal/grpcsrv/transport/grpc_metadata_test.go
  - MetaFromGRPC extracts host/IP/UA/auth/cookies; :authority fallback
  - cookiesFromMetadata parses multi-header cookies
  - ApplyToGRPC nil-safety

internal/mcp/schema_test.go
  - schemaForMessage for flat scalars + nested message (AppData)
  - **TestSchemaForMessage_CycleSafe** would have caught the original
    stack-overflow bug
  - Documents current oneof flattening as known limitation

internal/integration_tests/grpc_surface_test.go
  - TestGRPCStubsReturnUnimplemented: every one of the 18 stubbed RPCs
    verified to return codes.Unimplemented (locks down the contract so
    future migrations can't accidentally regress to OK or panic)
  - TestGRPCHealthCheckProtocol: grpc.health.v1.Health responds SERVING

internal/integration_tests/rest_openapi_test.go
  - /openapi.json serves valid swagger 2.0 with non-empty paths object

internal/integration_tests/mcp_stubs_test.go
  - MCP call to a stubbed tool returns CallToolResult{IsError:true} with
    "Unimplemented" in the text (vs the previous JSON-RPC-level error)

BLOCKING FIXES FROM REVIEW

cmd/root.go
  - --grpc-port default 8081 collided with --metrics-port. Moved gRPC to
    9091. Added a triple-port collision check (HTTP/metrics/gRPC) at
    startup; fail fast with a specific error message.

internal/grpcsrv/transport/grpc_metadata.go
  - MetaFromGRPC now extracts cookies from grpcgateway-cookie / cookie
    metadata. The old version silently dropped them, which would have
    broken every authenticated flow as soon as the SessionService stubs
    were replaced with real handlers.
  - ApplyToGRPC now emits ALL Set-Cookie metadata entries via md.Append.
    The old version sent only the first cookie, breaking the host-scoped
    + domain-scoped session-cookie pair.

internal/mcp/schema.go
  - schemaForMessage tracks visited descriptors. Without this, exposing
    any tool whose request contained google.protobuf.Value (e.g. AppData
    → Struct → Value → repeated Value) would stack-overflow at server
    boot. Cycle short-circuits to opaque `object`.

internal/mcp/server.go
  - Tool execution errors (gRPC Unimplemented / PermissionDenied / etc.)
    now surface as CallToolResult{IsError:true} with the gRPC status
    message — the MCP-spec way to give the LLM actionable text instead
    of a low-level JSON-RPC failure.
  - Replaced fragile json-null string compare with strings.TrimSpace+
    isJSONNull helper.

internal/mcp/scanner.go
  - Removed unused descriptorOptionsCarrier dead-code struct + always-
    failing type assertion in mcpToolFromMethod. Function is now what
    it was always trying to be: 4 lines.

internal/server/http_routes.go + gen/openapi/openapi.go
  - /openapi.json no longer reads via relative path (which broke in
    Docker / tests where cwd ≠ repo root). The spec is now embedded
    via go:embed.

NOT FIXED IN THIS PR (deferred)
  - --grpc-tls-cert/-key/-insecure flags are still placeholders. Tracked
    for a TLS-implementation PR alongside the metrics-listener TLS work.
  - Secrets in REST path (DELETE /v1/refresh-tokens/{token} etc.) flagged
    by reviewer; the migration to body-borne tokens is a proto-design
    change worth its own PR + design discussion.
  - MCP auth metadata propagation — punted; today's MCP-exposed tools are
    GetMeta (no auth needed) + 3 stubs. Real wiring lands when those
    stubs become real handlers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@lakhansamani
Copy link
Copy Markdown
Contributor Author

Superseded by #620, which consolidates this stack into a single PR against main. All blocking review findings from this PR were addressed in #620; see its body for the per-finding traceback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant