Skip to content

feat(pip): add PolicyClient for RFC-005 PDP integration (Option B)#10

Merged
beonde merged 3 commits intomainfrom
feature/rfc005-pdp-rpc
Mar 20, 2026
Merged

feat(pip): add PolicyClient for RFC-005 PDP integration (Option B)#10
beonde merged 3 commits intomainfrom
feature/rfc005-pdp-rpc

Conversation

@beonde
Copy link
Member

@beonde beonde commented Mar 20, 2026

Summary

Adds the Python-side Policy Integration Point (PIP) module for RFC-005, implementing Option B architecture where all PDP decision logic is delegated to the Go core's EvaluatePolicyDecision gRPC RPC.

Depends on: capiscio-core#43 (Go-side EvaluatePolicyDecision RPC)

Architecture

┌─────────────────────────┐
│   Python SDK (this PR)  │
│                         │
│  PolicyClient.evaluate()│──gRPC──▶ Go Core
│  ┌───────────────────┐  │         EvaluatePolicyDecision()
│  │ Obligation exec   │  │         ┌─────────────────────┐
│  │ (rate_limit, etc) │  │         │ PDP query + timeout │
│  │ Response propagate│  │         │ Decision cache      │
│  └───────────────────┘  │         │ Break-glass         │
└─────────────────────────┘         │ Enforcement modes   │
                                    └─────────────────────┘

New Files

capiscio_mcp/pip.py

  • PolicyClient — thin gRPC caller that builds PolicyDecisionRequest, sends to core, parses PolicyDecisionResponse
  • PIPConfig — PDP endpoint, timeout, enforcement mode, PEP ID, workspace, break-glass key path
  • PolicyResult — decision + obligations + metadata, with convenience properties (allowed, denied, pdp_error)
  • Obligation — parsed obligation with typed params dict
  • PolicyResult.execute_obligations() — dispatches obligations to registered async handlers

tests/test_pip.py — 23 tests

  • PolicyResult properties (allowed/denied/pdp_error for ALLOW, DENY, ALLOW_OBSERVE)
  • Obligation and PIPConfig dataclasses
  • Obligation execution: handler dispatch, unknown types skipped, exceptions logged
  • PolicyClient gRPC integration (mock): allow, deny, observe+unavailable, obligations parsed, bad JSON fallback, cache hit, break-glass override, badge-only mode, request field fidelity

Proto Updates

  • Regenerated gen/ stubs from capiscio-core feature/rfc005-pdp-rpc proto
  • Adds EvaluatePolicyDecision RPC + 6 new message types (PolicyDecisionRequest/Response, PolicySubject, PolicyAction, PolicyResource, PolicyConfig, MCPObligation)
  • Updated hand-written stubs with matching dataclasses for IDE support

Test Results

  • 373/373 tests pass (including 23 new PIP tests)
  • No regressions

Option B architecture: delegates all PDP decision logic to Go core's
EvaluatePolicyDecision RPC. Python SDK handles obligation execution
(context-dependent) and response propagation.

New files:
- capiscio_mcp/pip.py: PolicyClient, PIPConfig, PolicyResult, Obligation
  - PolicyClient.evaluate() builds request, calls gRPC, parses response
  - PolicyResult.execute_obligations() dispatches to registered handlers
  - PolicyResult.allowed/denied/pdp_error convenience properties

- tests/test_pip.py: 23 tests covering:
  - PolicyResult properties (allowed/denied/pdp_error)
  - Obligation dataclass and execution
  - PIPConfig defaults and custom values
  - PolicyClient gRPC integration (mock): allow, deny, observe, cache,
    break-glass, obligations, bad JSON, request field fidelity

Proto updates:
- Regenerated gen/ stubs from capiscio-core feature/rfc005-pdp-rpc proto
  (adds EvaluatePolicyDecision RPC + 6 new message types)
- Updated hand-written stubs with matching dataclasses for IDE support
Copilot AI review requested due to automatic review settings March 20, 2026 18:30
@github-actions
Copy link

✅ Integration tests passed! capiscio-core gRPC tests working.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds the Python Policy Integration Point (PIP) for RFC-005 by introducing a thin PolicyClient that delegates policy decisions to capiscio-core’s new EvaluatePolicyDecision gRPC RPC, returning a PolicyResult with obligations for the SDK to execute.

Changes:

  • Added capiscio_mcp.pip with PolicyClient, PIPConfig, PolicyResult, and obligation execution support.
  • Added a new tests/test_pip.py suite covering PolicyResult behavior, obligation handling, and mocked gRPC evaluation.
  • Regenerated/updated proto stubs to include the EvaluatePolicyDecision RPC and related message types.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
capiscio_mcp/pip.py New PIP client module that builds a PolicyDecisionRequest, calls core via gRPC, parses obligations, and exposes PolicyResult.
tests/test_pip.py New test suite for PIP behavior, obligation execution, and request/response parsing.
capiscio_mcp/_proto/gen/capiscio/v1/mcp_pb2_grpc.py Generated gRPC stub updated with EvaluatePolicyDecision and version gating logic.
capiscio_mcp/_proto/gen/capiscio/v1/mcp_pb2.py Generated protobuf definitions updated to include RFC-005 messages and RPC.
capiscio_mcp/_proto/capiscio/v1/mcp_pb2_grpc.py Hand-written async stub placeholder updated with EvaluatePolicyDecision method signature.
capiscio_mcp/_proto/capiscio/v1/mcp_pb2.py Hand-written placeholder message definitions extended with RFC-005 dataclasses.

- Regenerated proto stubs from capiscio-core main (PR #43 merged)
- PolicyConfig.breakglass_public_key_path (string) → breakglass_public_key (bytes)
- Updated PIPConfig, PolicyClient.evaluate(), and tests
- Fixed regenerated grpc stub import path
@github-actions
Copy link

✅ Integration tests passed! capiscio-core gRPC tests working.

- Remove Obligation.id (MCPObligation proto has no id field)
- Validate json.loads returns dict before using as params
- Downgrade grpcio version check from RuntimeError to RuntimeWarning
- Update tests to match proto shape (no id field on obligations)
Copilot AI review requested due to automatic review settings March 20, 2026 20:17
@github-actions
Copy link

✅ Integration tests passed! capiscio-core gRPC tests working.

@beonde beonde merged commit d3dc020 into main Mar 20, 2026
12 checks passed
@beonde beonde deleted the feature/rfc005-pdp-rpc branch March 20, 2026 20:19
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Comment on lines +186 to +189
badge_jti: str = "",
ial: str = "",
trust_level: str = "",
badge_exp: int = 0,
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trust_level is typed as str and passed directly into PolicySubject.trust_level (a proto string field). Most callers in this codebase represent trust levels as ints/TrustLevel (e.g., GuardResult.trust_level), so passing an int here would raise a TypeError when constructing the protobuf message. Consider accepting int | str (and/or TrustLevel) and normalizing via str(trust_level) before building the request.

Copilot uses AI. Check for mistakes.
Comment on lines 5 to +16
@@ -12,8 +12,8 @@
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
33,
4,
31,
1,
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generated protobuf module enforces Protobuf Python Version: 6.31.1 via ValidateProtobufRuntimeVersion(...), which will raise at import time if the runtime protobuf major version is < 6. This is incompatible with the declared dependency floor (protobuf>=4.25.0), so installs that satisfy pyproject.toml can still break at runtime. Either bump the dependency to protobuf>=6.31.1 (or >=6.x) or regenerate the stubs with a protoc/protobuf version that matches the supported protobuf range.

Copilot uses AI. Check for mistakes.
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.

2 participants