Learning Objectives
By the end of this module, you will be able to:
- Keep bundle acquisition, cryptographic verification, policy enforcement, and model invocation as separate gates
- Fail closed when required VCP evidence is absent or invalid
- Format a verified bundle for provider-neutral prompt injection
- Record privacy-aware verification evidence
4.1 — The Trust Boundary
A VCP-enabled chat application has an explicit sequence:
Load bytes
→ validate schema and limits
→ verify hash, signatures, trust, time, revocation, budget, and scope
→ apply local enforcement policy
→ format verified constitutional content
→ call the selected model provider
→ retain a privacy-aware audit record Do not send unverified bundle content to a model. Parsing and formatting are not substitutes for verification.
4.2 — Project Setup
# From the root of an immutable VCP-SDK checkout
python -m venv .venv
. .venv/bin/activate
python -m pip install ./python SDK 4.2.0 is currently source-only. No registry release is claimed. Record the checkout commit before using it as deployment evidence.
Install the SDK for your selected model provider separately. VCP does not require one provider and does not hide provider credentials inside its package.
4.3 — Load Trust and Bundle Data
Your application must define where bundles and trust anchors come from. Keep those adapters narrow and reviewable:
bundle = bundle_repository.load("family.safe.guide", "1.2.0")
trust = trust_repository.load_for_environment("production")
# These two repositories are application-owned adapters.
# Treat fetched bundle bytes and registry responses as untrusted input. Pin issuer and auditor keys through TrustConfig. Never infer
trust merely because a bundle names a familiar issuer.
4.4 — Verify and Enforce
from vcp import (
BundleExpiryPlugin,
Orchestrator,
PDPEnforcer,
RefusalBoundaryPlugin,
VerificationResult,
)
verification = Orchestrator(trust).verify(bundle)
if verification is not VerificationResult.VALID:
raise PermissionError(
"VCP bundle rejected: " + verification.name
)
enforcer = PDPEnforcer(fail_closed=True)
enforcer.register(BundleExpiryPlugin())
enforcer.register(RefusalBoundaryPlugin())
policy = enforcer.evaluate(
bundle,
content=user_message,
verification_result=verification,
)
if not policy.allowed:
raise PermissionError("VCP policy blocked this request") The built-in enforcer produces ALLOW, BLOCK, MODIFY, or ESCALATE decisions. In the current SDK,
an unhandled escalation is promoted to a block. Applications that need human
review must build and test that workflow explicitly.
4.5 — Format Only After Verification
from vcp import InjectionFormat, InjectionOptions, format_injection
vcp_prompt = format_injection(
bundle,
options=InjectionOptions(
format=InjectionFormat.HEADER_DELIMITED,
include_tokens=True,
include_attestation=True,
),
)
messages = [
{"role": "system", "content": vcp_prompt},
{"role": "user", "content": user_message},
]
# Send messages through your provider adapter only after every gate above passes.
reply = await model_provider.respond(messages) Important:
format_injectionformats a bundle. Its type signature cannot prove that your application calledverifyfirst. Preserve that ordering in one reviewed function and cover the negative path with tests.
4.6 — Add Adaptation Context
Encode contextual signals separately from constitutional bundle content:
from vcp.adaptation import ContextEncoder
context = ContextEncoder().encode(
time="evening",
space="home",
company="children",
)
context_wire = context.encode()
# Your application decides whether and where this bounded wire value is shared. Context does not acquire confidentiality merely because it is encoded. Apply consent, minimisation, platform filtering, retention limits, and logging redaction at the application boundary.
4.7 — Record Verification Evidence
from vcp import AuditLevel, AuditLogger
audit = AuditLogger(level=AuditLevel.STANDARD)
audit.log_verification(
bundle,
verification,
session_id=session_id,
request_id=request_id,
)
# Persist through a controlled callback or export path with your own
# access control and retention policy. The SDK hashes session and request identifiers before storing them. That reduces exposure but does not remove your obligations around access, retention, deletion, and incident response.
4.8 — Test the Failure Paths
- Missing bundle and missing trust anchor
- Hash mismatch, invalid signature, and invalid attestation
- Expired, not-yet-valid, revoked, and replayed bundles
- Scope or audience mismatch
- Enforcement plugin exception under fail-closed operation
- Provider failure after verification, without leaking raw private context into logs
Exercise
Run the SDK's examples/python/05_full_pipeline.py. Then
tamper with the bundle content and confirm that verification fails
before formatting or model invocation.
See It in Action
The Gentian demo illustrates portable preferences. The demo is an explanatory application, not evidence that a third-party platform implements VCP.