Module 7: Real-world integration patterns

Place verification and enforcement at a boundary your architecture can actually defend.

DEV, PROVIDER 25 min

Learning objectives

By the end of this module, you will be able to:

  • Choose between gateway, middleware, and embedded verification
  • Pass an explicit verification result into local enforcement
  • Compose multiple verified constitutions without bypassing trust checks
  • Define degraded operation from system risk, rather than from convenience

7.1 — Integration patterns

The reference SDK is a local library, so verification runs inside your own system and needs no hosted decision service. You still have to choose where in your system it runs. The three patterns below place it at a gateway, in middleware, or directly in application code.

Pattern A: Gateway boundary

A gateway verifies bundles and applies policy before a request reaches a model provider. This keeps trust configuration and audit controls in one place. The cost is that every request now depends on the gateway, so a compromise or outage there affects everything behind it.

Application
    → VCP gateway: load, verify, enforce, minimize
    → model provider adapter
    → response and audit evidence

Pattern B: Application middleware

Middleware works well when every request to the model passes through a single service you control. The example below assumes that bundle_repository and trust are application-owned dependencies:

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from vcp import (
    Orchestrator,
    PDPEnforcer,
    RefusalBoundaryPlugin,
    VerificationResult,
)

app = FastAPI()
enforcer = PDPEnforcer(fail_closed=True)
enforcer.register(RefusalBoundaryPlugin())


@app.middleware("http")
async def vcp_middleware(request: Request, call_next):
    if request.method != "POST":
        return await call_next(request)

    bundle = bundle_repository.for_request(request)
    verification = Orchestrator(trust).verify(bundle)
    if verification is not VerificationResult.VALID:
        return JSONResponse(
            status_code=403,
            content={"error": "VCP verification failed"},
        )

    decision = enforcer.evaluate(
        bundle,
        content=(await request.body()).decode("utf-8"),
        verification_result=verification,
    )
    if not decision.allowed:
        return JSONResponse(
            status_code=403,
            content={"error": "VCP policy blocked request"},
        )

    request.state.verified_vcp_bundle = bundle
    return await call_next(request)

The example above does not cap the size of the request body. In production, set a limit before decoding it. Also keep sensitive policy evidence out of responses to callers, and make sure downstream handlers cannot swap the verified bundle for fresh, untrusted input.

Pattern C: Embedded library

Call the SDK directly at the point where a model prompt or tool action is authorized. This reduces infrastructure, while requiring every call site to preserve the same verification and enforcement sequence.

7.2 — Multi-constitution composition

Composition means combining several constitutions, such as an organization-wide one and a domain-specific one, into a single context for the model. Verify each bundle on its own first. Combining bundles never passes trust from one to another, so an unverified bundle stays untrusted even beside a verified one:

from vcp import (
    Orchestrator,
    VerificationResult,
    format_multi_constitution_injection,
)

bundles = [organization_bundle, domain_bundle]
orchestrator = Orchestrator(trust)

for bundle in bundles:
    result = orchestrator.verify(bundle)
    if result is not VerificationResult.VALID:
        raise PermissionError("Constitution set is not fully verified")

system_context = format_multi_constitution_injection(bundles)

format_multi_constitution_injection lists the verified constitutions in composition-layer order and marks higher layers as taking precedence. It does not check whether their rules contradict each other. Use the SDK's Composer when you need explicit CSM-1 semantic conflict handling, for example when one constitution allows what another forbids. Test ordering, precedence, strictness, and conflict behavior with your own policy examples.

7.3 — Degraded operation

Degraded operation is what your system does when part of the verification chain is unavailable, such as an unreachable revocation endpoint or bundle store. A bundle that could not be verified is still rejected; the strategy decides what, if anything, runs without it. Group your actions into classes by the harm a wrong decision could cause, then choose a strategy for each class and document it before an outage:

StrategyUseWhat it requires
Fail closedSafety-critical, financial, medical, or irreversible actionsDeny when bundle, trust, revocation, scope, or verification evidence is unavailable
Verified cached bundleBounded offline operationPreviously verified bytes, valid time window, local trust state, replay controls, and an explicit maximum age
Restricted fallbackLow-risk availability pathsA separately reviewed capability subset with no high-impact actions
Audit-only modeObservation or staged rolloutClear user and operator indication that enforcement is not active

A generic fail-open path lets requests through unchecked whenever verification cannot run. That is unsuitable for any control whose absence creates the very risk it is meant to limit.

7.4 — Error handling

verify_or_raise raises a VerificationError instead of returning a result, which suits code that already handles failures with exceptions. The error carries the failed verification result. The log below records that result's name and a fixed message, never the bundle itself.

from vcp import VerificationError

try:
    orchestrator.verify_or_raise(bundle)
except VerificationError as error:
    logger.warning(
        "VCP verification rejected bundle",
        extra={"code": error.result.name},
    )
    return deny_response("Value verification unavailable")

Do not log raw bundle content, context, keys, or user identifiers in the error path.

7.5 — Performance and capacity

  • Benchmark verification, revocation lookup, context encoding, and provider latency separately
  • Bound bundle size and context growth before cryptographic work
  • Use the SDK's bounded replay and revocation caches
  • Cache only exact verified bytes with trust and freshness metadata
  • Measure latency for your own integration on representative hardware; the SDK makes no universal latency claim, so do not rely on one

Exercise

Test the Pattern B middleware with two bundles. The first has a deliberately invalid signature; it must return INVALID_SIGNATURE and be denied. The second has an unreachable revocation endpoint; it must return REVOCATION_UNAVAILABLE. The example denies every result other than VALID, so add a branch for REVOCATION_UNAVAILABLE that applies your degraded-operation policy. Confirm that neither bundle reaches the model and that each action class follows the policy you documented for it.

See it in action

The Relay demo illustrates context handoff between agents. It is a scenario demonstration, not a benchmark or third-party conformance result.