Status: Draft, pre-1.0
This document describes the security and privacy assumptions behind the current CCP draft. It is not a certification claim, complete risk assessment, or substitute for an implementer’s own threat model.
CCP is designed to protect:
The current draft assumes these boundaries:
The draft is intended to reduce these risks:
The current draft does not yet define:
Implementers must address these items in their own deployment architecture until the draft defines them or explicitly adopts an existing primitive.
The term Actor currently covers people, organizations, systems, agents, and services. These have different trust postures:
Future drafts should add more explicit actor typing or delegation semantics if design partners need interoperable policy decisions across these roles.
PermissionGrant is a schema-backed authorization record, but grant transport and proof are intentionally not standardized yet. This creates interoperability risk:
grant_id is sufficient authority; it is not.Until this is specified, compatible servers should treat grant identifiers as lookup keys into trusted authorization state, not bearer secrets, and should fail closed when grant status, issuer authority, subject pet, requester, purpose, scope, facility boundary, or service window cannot be verified.
The unresolved sub-decisions (issuance, storage, possession, revocation propagation) and the candidate primitives under evaluation are catalogued in docs/implementers/compatibility-risks.md §Decisions Needed Before 1.0. The decision is tracked in GitHub issue #6. Facility Truth v1 does not require a PermissionGrant, so this decision does not gate Facility Truth adoption, but it must resolve before Commerce Context, Care Facility Context, or Care Network Lookup can interoperate across organizations.
Cross-profile inference is a residual risk CCP does not fully prevent and does not promise to eliminate by 1.0. Visibility precedence rules prevent many single-response leaks, but they do not prevent a requester who holds grants for more than one profile — or who makes repeated calls within a single profile — from correlating omissions, partial responses, freshness timestamps, and summaries across calls to reconstruct restricted context that no single response would have disclosed. The canonical schemas cannot detect cross-call correlation; only the authorization layer can. The stable line is expected to ship with this risk surface acknowledged rather than closed; ongoing work narrows it, not closes it.
SPEC.md Conformance Requirements state normatively that servers MUST NOT rely on per-profile narrowness alone, and that servers granting multi-profile (or repeat single-profile) access for the same requester SHOULD apply per-requester rate limits across all authorized profiles, correlation-aware authorization logging with enough metadata for retrospective abuse review, and per-request minimization (return only fields the declared purpose needs, even when granted scopes would allow more). In addition, compatible servers should:
These mitigations are necessary but not sufficient. They reduce the inference surface; they do not eliminate it.
Stronger guidance is under ongoing research and tracked in GitHub issue #7. The candidate sub-decisions and primitives below are documented so that implementers know what shape future-draft work could take; none are endorsed in 0.1.0-draft, and adoption is not a precondition for the stable line. Four sub-decisions remain open:
correlation_token, requester_session_id, abuse_review_id) that lets independent profile servers operated by different teams join authorization records into a shared abuse-review pipeline without bilateral coordination, or whether each integrator invents its own join key.SHOULD into machine-checkable behavior (e.g., per-purpose minimum-required-field tables, or a minimization_profile field), or leaves it as policy.None of the following are endorsed in 0.1.0-draft. They are listed so implementers can recognize the shape of future-draft work, not as a roadmap commitment:
correlation_token request field — a low-surface addition: each profile request schema gains one optional opaque-string field that profile servers MAY log alongside authorization decisions. Cheap to specify and adopt; does not by itself enforce rate limits or minimization, and creates a new privacy surface if the token is owner-derived rather than requester-derived. Binding properties differ sharply by who assigns the token. A client-assigned token carries no server-side binding: a malicious requester can omit, rotate, or forge it to defeat cross-call correlation in audit logs. A server-assigned token (server-generated identifier returned in the response that the client must echo on subsequent calls) avoids the forgery surface but still admits short-window correlation evasion if the client rotates tokens between calls. Any future-draft design that adopts correlation_token should treat the server’s own authenticated-principal identity as the authoritative join key and treat the token as an optional additional signal, never as the primary identifier; the client-assigned warning above applies to the client-assigned shape specifically.CCP-Requester-Quota-Remaining, CCP-Requester-Quota-Window) — gives clients backpressure signals across profiles, but lives at the transport layer (HTTP/MCP) rather than in the canonical contract, and depends on the rate-limit envelope decision above.correlation_token for cross-organization joins plus rate-limit headers for backpressure; leaves minimization and profile-combination policy to a later draft. Largest surface to specify and adopt, but covers two of the four gaps.A worked synthetic attack-and-defense example lives in docs/implementers/cross-profile-inference.md.
Facility Truth covers mostly public operational facts, but public-by-nature does not mean risk-free. Incorrect hours, stale service eligibility, invented certifications, or outdated booking methods can still harm facilities and clients.
The v1 Facility Truth profile ships only public-fact scopes (facility.profile.read, facility.hours.read, facility.services.read, facility.contact_methods.read, facility.service_area.read, facility.acceptance_criteria.read, facility.booking_methods.read, facility.policies.summary.read) and does not require a PermissionGrant. Removing the grant requirement removes the issuer-binding control surface for these scopes; the freshness contract carries its safety load instead. Every returned Facility Truth field’s provenance MUST carry verified_at, and stale facts MUST be omitted with source_stale rather than returned. Unverified facts MUST be omitted with not_verified rather than guessed. The “facility-public” rule and the no-pet_id subject-boundary rule are enforced by the canonical schemas and conformance runner.
Higher-scrutiny facility scopes — certifications, insurance statements, capacity status, staff credentials — are deferred to a future partner-only Facility Truth slice with its own scopes, purpose rules, facility_partner_visible visibility class, and grant shape (likely an additive subject_facility_id on PermissionGrant). v1 implementers MUST NOT assume the v1 no-grant semantics generalize to those future scopes.
Cross-facility inference is a residual risk: a requester enumerating many facility_id values in succession can build behavioural signals (which facilities exist, which scopes are denied, when a facility last verified) even when each individual response is correctly minimized. Implementations should rate-limit, log, and review enumeration patterns outside the canonical schema layer.
Design partners should review: