Skip to content

refactor: extract shared DIFC enforcement pipeline to internal/guard/pipeline.go#6685

Merged
lpcox merged 4 commits into
mainfrom
copilot/duplicate-code-difc-pipeline
May 29, 2026
Merged

refactor: extract shared DIFC enforcement pipeline to internal/guard/pipeline.go#6685
lpcox merged 4 commits into
mainfrom
copilot/duplicate-code-difc-pipeline

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 29, 2026

The 6-phase DIFC enforcement pipeline was independently implemented in both internal/proxy/handler.go and internal/server/unified.go (~100 lines of near-identical security logic), creating drift risk: a security fix in one path could silently leave the other exposed.

Changes

New: internal/guard/pipeline.go

Shared pipeline types and phase helpers placed in guard (sits above difc, below proxy/server — no circular import):

  • PipelineInput — unified inputs struct (agent ID, tool name, args, guard, evaluator, registry, capabilities, enforcement mode, backend caller)
  • PipelinePreResult — outputs from phases 0–2 (agent labels, labeled resource, operation, coarse outcome, eval result)
  • PipelineAccessDenied — typed error for Phase 2 denial; carries EvalResult, Resource, and AgentLabels so callers can formulate context-appropriate denial responses (HTTP 403 vs MCP error)
  • RunPipelinePrePhases — phases 0–2: get/create agent labels, store tool args in context, LabelResource, coarse access check
  • RunPipelinePhase4 — conditional LabelResponse (gated by ShouldCallLabelResponse)
  • RunPipelinePhase6 — label accumulation in propagate mode; falls back to resource labels when labeledData is nil (aligns proxy behavior with server — proxy previously skipped this fallback)

Refactored: proxy/handler.go and server/unified.go

Phases 0–2, 4, and 6 replaced with shared helper calls. Context-specific logic remains inline:

  • Phase 3: HTTP forward (proxy) vs MCP backend call via circuit breaker (server)
  • Phase 5: GraphQL/REST response reconstruction (proxy) vs MCP collection filtering with notices and singular-item errors (server)
// Before (duplicated in both files):
agentLabels := s.AgentRegistry.GetOrCreate("proxy")
resource, operation, err := s.guard.LabelResource(ctx, toolName, args, backend, s.Capabilities)
coarseOutcome, evalResult := difc.EvaluateCoarseAccess(s.Evaluator, agentLabels.Secrecy, ...)
switch coarseOutcome { /* ... */ }

// After:
ctx, pre, err := guard.RunPipelinePrePhases(ctx, pipelineIn)
if denied, ok := err.(*guard.PipelineAccessDenied); ok { /* caller-specific denial */ }

New: internal/guard/pipeline_test.go

16 unit tests covering all shared phases: Phase 0 label retrieval and context injection, Phase 1 error propagation, Phase 2 allow/bypass-for-read/deny outcomes, Phase 4 conditional labeling, Phase 6 accumulation across all three enforcement modes.

Copilot AI added 2 commits May 29, 2026 13:02
Eliminates the duplicate 6-phase DIFC enforcement pipeline that existed
independently in proxy/handler.go and server/unified.go.

- Add internal/guard/pipeline.go with PipelineInput, PipelinePreResult,
  PipelineAccessDenied, RunPipelinePrePhases (phases 0–2), RunPipelinePhase4,
  and RunPipelinePhase6 shared helpers
- Refactor internal/proxy/handler.go to use shared helpers for phases 0–2,
  4, and 6; proxy-specific phase 3 (HTTP forward) and phase 5 (GraphQL/REST
  response processing) remain inline
- Refactor internal/server/unified.go to use shared helpers for phases 0–2,
  4, and 6; server-specific phase 3 (MCP backend call via circuit breaker)
  and phase 5 (MCP filtering/notices) remain inline
- Add internal/guard/pipeline_test.go with 16 focused tests covering all
  shared pipeline helpers (phases 0–2, 4, 6) including denial, bypass-for-
  read, label accumulation in all three enforcement modes, and error paths

Behavioral equivalence: Phase 6 now always falls back to resource labels
when labeledData is nil in both callers (was previously only done in
unified.go). All existing proxy and server DIFC tests continue to pass.
Address code review feedback on pipeline_test.go.
Copilot AI changed the title [WIP] Refactor DIFC pipeline to eliminate duplicate code refactor: extract shared DIFC enforcement pipeline to internal/guard/pipeline.go May 29, 2026
Copilot finished work on behalf of lpcox May 29, 2026 13:04
Copilot AI requested a review from lpcox May 29, 2026 13:04
@lpcox lpcox marked this pull request as ready for review May 29, 2026 13:08
Copilot AI review requested due to automatic review settings May 29, 2026 13:08
Copy link
Copy Markdown
Contributor

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

This PR centralizes the shared DIFC enforcement phases used by both proxy and unified MCP server paths, reducing duplicated security-sensitive pipeline logic.

Changes:

  • Adds internal/guard/pipeline.go with shared helpers for phases 0–2, 4, and 6.
  • Refactors internal/proxy/handler.go and internal/server/unified.go to call the shared pipeline helpers while keeping transport-specific execution/filtering inline.
  • Adds unit tests for the new guard pipeline helpers.
Show a summary per file
File Description
internal/guard/pipeline.go Introduces shared DIFC pipeline input/result types and phase helpers.
internal/guard/pipeline_test.go Adds unit coverage for the extracted pipeline phases.
internal/proxy/handler.go Replaces duplicated proxy DIFC phase logic with shared guard pipeline calls.
internal/server/unified.go Replaces duplicated unified-server DIFC phase logic with shared guard pipeline calls.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 4/4 changed files
  • Comments generated: 1

Comment thread internal/guard/pipeline_test.go
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@lpcox lpcox merged commit cecc604 into main May 29, 2026
16 checks passed
@lpcox lpcox deleted the copilot/duplicate-code-difc-pipeline branch May 29, 2026 13:14
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.

[duplicate-code] Duplicate Code Pattern: DIFC Pipeline Structural Duplication in proxy/handler.go and server/unified.go

3 participants