feat(rpc): add EvaluatePolicyDecision gRPC endpoint (RFC-005 Option B)#43
Merged
feat(rpc): add EvaluatePolicyDecision gRPC endpoint (RFC-005 Option B)#43
Conversation
Centralise PDP decision logic in Go core so Python, Node and .NET SDKs become thin gRPC callers instead of each re-implementing the full PIP. Proto changes: - Add EvaluatePolicyDecision RPC to MCPService - Add PolicyDecisionRequest/Response and sub-messages (PolicySubject, PolicyAction, PolicyResource, PolicyConfig) Handler (internal/rpc/policy_decision.go): - Full PDP query with configurable timeout - Enforcement mode semantics (EM-GUARD/OBSERVE/AUDIT/NONE) - Break-glass JWS override with Ed25519 validation - In-memory decision cache with TTL bounded by badge expiry - Obligation marshalling via ObligationRegistry - PDP unavailability returns response (not error) per protocol: EM-OBSERVE → ALLOW_OBSERVE + error_code others → DENY + error_code - Transaction ID (UUID v7) on every response Tests (23 cases): - NoPDP, PDPAllow/Deny, PDPUnavailable (fail-closed + observe) - Break-glass, cache hit, cached deny observe override - Timeout, invalid responses, obligation marshalling - All enforcement modes, TxnID format, PDP request fidelity
Contributor
There was a problem hiding this comment.
Pull request overview
Adds an RFC-005 “Option B” gRPC surface to centralize PDP-backed policy evaluation in capiscio-core so SDKs can call a single RPC for policy decisions.
Changes:
- Extends
MCPServicewith a newEvaluatePolicyDecisionRPC and associated request/response messages. - Implements
EvaluatePolicyDecisionserver-side logic (PDP call, cache lookup, break-glass handling, response shaping). - Adds unit tests and regenerates Go protobuf/grpc bindings.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| proto/capiscio/v1/mcp.proto | Adds the new RPC and RFC-005 policy decision message types/fields. |
| pkg/rpc/gen/capiscio/v1/mcp_grpc.pb.go | Regenerated gRPC client/server stubs to include EvaluatePolicyDecision. |
| pkg/rpc/gen/capiscio/v1/mcp.pb.go | Regenerated protobuf message types for the new RFC-005 messages. |
| internal/rpc/policy_decision.go | Implements the new RPC handler (PDP query, caching, break-glass, obligations handling). |
| internal/rpc/policy_decision_test.go | Adds test coverage for the new RPC behavior. |
| internal/rpc/mcp_service.go | Wires new cache/obligation registry fields into MCPService construction. |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
- Proto: change breakglass_public_key_path (string) to breakglass_public_key (bytes) to eliminate filesystem access from RPC boundary (comments #8, #9) - Remove server-side obligation enforcement; obligations returned to SDK caller per Option B protocol boundary (comments #1, #2, #3) - Sanitize error messages in handlePDPUnavailable; log raw errors server-side, return stable 'policy service unavailable' to callers (comment #6) - Add classifyPDPError to distinguish pdp_timeout, pdp_invalid_response, and pdp_unavailable error codes (comment #7) - Validate enforcement_mode before badge-only early return (comment #10) - Fix newTestService to propagate errors via require.NoError (comment #5) - Add break-glass test coverage: valid override, wrong key, no key configured, scope mismatch, bad key size (comment #4) - Add InvalidEnforcementMode_NoPDP test for badge-only + invalid mode - Add TestClassifyPDPError with 8 error classification cases
Extract buildPIPRequest helper to move 3 conditional branches out of the main handler, reducing gocyclo from 16 to 13 (limit: 15).
- badgeExpTTL returns 0 when badge_exp missing (skip cache per RFC-005) (#11) - Remove unused pipReq param from handleBreakGlass (#12) - Include enforcement_mode in cache key via variadic CacheKeyComponents (#17) - Handle context.Canceled as client cancellation (return ctx.Err()), not as PDP timeout (#19) - Extract queryPDP helper to reduce EvaluatePolicyDecision complexity to 11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Centralises PDP decision logic in Go core's gRPC service so Python, Node and .NET SDKs become thin gRPC callers instead of each re-implementing the full PIP.
Architecture decision: Option B — single Go implementation of PDP evaluation exposed via gRPC RPC. SDKs call
EvaluatePolicyDecisionand only handle obligation execution (context-dependent: rate limiting, logging, etc.) and response propagation.Changes
Proto (
proto/capiscio/v1/mcp.proto)EvaluatePolicyDecisionRPC onMCPServicePolicyDecisionRequest,PolicyDecisionResponse,PolicySubject,PolicyAction,PolicyResource,PolicyConfigHandler (
internal/rpc/policy_decision.go, ~310 lines)ObligationRegistryALLOW_OBSERVE+error_codeDENY+error_codeService (
internal/rpc/mcp_service.go)decisionCacheandobligationRegfields toMCPServiceTests (
internal/rpc/policy_decision_test.go, 23 cases)Protocol Boundary
Test Results
go vet ./...— cleango test ./...— 17/17 packages pass (excl. integration)Related