From 59597f94dc6c52563eb8adaa1dbc292ee7965e74 Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Tue, 16 Jun 2026 08:58:29 +0200 Subject: [PATCH] Add data-class scheme skeleton; separate label-schemes from host architectures - schemes/data-class.md: skeleton for the structured classification taxonomy the trust-annotations 'sensitive' boolean deliberately omits (class + regulatory scope + org labels), shaped as open questions and attributed to the SEP-1913 reviewers who pushed for it (JustinCappos, olaservo, Mossaka, krubenok, localden). - schemes/README.md: list data-class under 'Schemes here'; add verified label- scheme candidates (Permissive IFC 2410.03055, AirGapAgent 2405.05175); move CaMeL and the design-pattern catalogue into a new 'Not schemes: host architectures' section, since they govern host control-flow rather than producing a per-result data label. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- schemes/README.md | 20 +++++-- schemes/data-class.md | 123 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 schemes/data-class.md diff --git a/schemes/README.md b/schemes/README.md index a7d63f1..b870e71 100644 --- a/schemes/README.md +++ b/schemes/README.md @@ -17,17 +17,19 @@ here rather than as a top-level extension. | Scheme | `evidenceRef.type` | Status | Source | | :--- | :--- | :--- | :--- | | [FIDES information-flow control](./ifc-fides.md) | `ifc.fides.v1` | Draft skeleton | [arXiv:2505.23643](https://arxiv.org/abs/2505.23643) | +| [Data classification](./data-class.md) | `data-class.v1` | Draft skeleton | SEP-1913 taxonomy (`class` + regulatory scope) | ## Candidate schemes (not yet drafted) The open `type` slot is designed to carry the range of models raised in the [SEP-1913](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1913) -review and the surrounding literature. Each is a candidate for its own scheme doc: +review and the surrounding literature. Each is a candidate for its own scheme doc. +A scheme produces a **per-result data label** a server attaches: | Approach | Likely `type` | Source | | :--- | :--- | :--- | -| Coarse data classification (level + regulatory scope) | `data-class.v1` | SEP-1913 taxonomy (e.g. `confidential:hipaa` shape) | -| Design-pattern controls (Plan-Then-Execute, Dual LLM, Map-Reduce) | — | [arXiv:2506.08837](https://arxiv.org/abs/2506.08837) | +| Permissive information-flow labels (influence-based propagation) | `ifc.permissive.v1` | [arXiv:2410.03055](https://arxiv.org/abs/2410.03055) | +| Contextual-integrity classification (per-task minimisation) | `ci.airgap.v1` | [arXiv:2405.05175](https://arxiv.org/abs/2405.05175) | | ShardGuard | — | cited in SEP-1913 | | Capability-token constraints (SINT) | — | SEP-1913 review thread | | Caller/tool cosigning | — | SEP-1913 review thread | @@ -37,6 +39,18 @@ review and the surrounding literature. Each is a candidate for its own scheme do These are leads, not commitments. A candidate becomes a scheme when someone drafts it to the bar below; until then the slot simply stays open for it. +## Not schemes: host architectures + +Some models raised in the same discussion are **host/client control-flow +architectures**, not data labels — they decide what to *do* with information, +they don't produce a per-result record a server attaches. They are prior art (see +[`related-work.md`](../docs/related-work.md)), not entries here: + +| Approach | Why it isn't a scheme | Source | +| :--- | :--- | :--- | +| CaMeL (capability-based control/data-flow) | A host runtime; a capability token it issues *could* be referenced via `evidenceRef`, but the architecture isn't a label | [arXiv:2503.18813](https://arxiv.org/abs/2503.18813) | +| Design-pattern controls (Plan-Then-Execute, Dual LLM, Map-Reduce) | Client-side execution patterns, nothing on the wire | [arXiv:2506.08837](https://arxiv.org/abs/2506.08837) | + ## Bar for adding a scheme A scheme doc should state: diff --git a/schemes/data-class.md b/schemes/data-class.md new file mode 100644 index 0000000..74bf932 --- /dev/null +++ b/schemes/data-class.md @@ -0,0 +1,123 @@ +--- +title: Data classification (data-labelling scheme) +--- + +> ⚠️ **Experimental scheme skeleton.** This is one **data-labelling scheme** that +> fills the [`trust-annotations`](../specification/draft/trust-annotations.mdx) +> `evidenceRef` slot via `type: "data-class.v1"`. It is **not** an MCP extension +> and **not** a sibling of the extensions — it is the home for the richer +> classification taxonomy that the extension's coarse `sensitive` boolean +> deliberately leaves out. See [Why a scheme](#why-a-scheme-not-a-wire-field). + +**Scheme** — fills `trust-annotations`'s `evidenceRef` slot, selected by +`evidenceRef.type == "data-class.v1"`. Not an extension. + +## Abstract + +This scheme defines `data-class.v1`, an entry for the `trust-annotations` +`evidenceRef` slot that carries a **structured data classification**: a coarse +sensitivity level plus zero or more regulatory scopes and optional org-defined +labels. It is the structured counterpart to the extension's single +`sensitive: boolean`, for deployments that need to express *which* regulated +category a result falls under (e.g. HIPAA, GDPR, PCI-DSS) without putting that +taxonomy on the wire for every server. + +## Why a scheme, not a wire field + +The `trust-annotations` extension keeps only `sensitive: boolean` on the wire. +That coarse signal is universally client-actionable and cheap, and — critically +— it cannot become wrong as regulation changes. A richer classification was +asked for repeatedly in review, in three different shapes: + +- a **linear** `sensitiveHint: low | medium | high`, which + [@JustinCappos](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/711#issuecomment-2967516811) + rejected: sensitivity is set-theoretic (a card number and a medical record are + both sensitive but to *different* readers), not a single scale; +- **org-defined vocabularies** rather than a fixed enum + ([@olaservo](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/711#issuecomment-2968743154); + [@Mossaka](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/711#issuecomment-2971788308) + proposed reverse-DNS `classification.labels`); +- a **class + regulatory scope** pairing such as `confidential:hipaa` + ([@krubenok](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1913#discussion_r3103485194); + carried into SEP-2061 by @rreichel3). + +Against all three, [@localden](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1913#issuecomment-4037623595) +warned that a taxonomy baked into the protocol is very hard to remove if it turns +out wrong. A scheme resolves the tension: the taxonomy evolves behind a `type` +value, on its own clock, while the wire keeps the boolean that can never rot. + +## Motivation + +A regulated deployment needs to know not just *that* a result is sensitive but +*under which regime*, so the host can apply the matching control (HIPAA minimum- +necessary, GDPR purpose limitation, PCI-DSS storage rules). The boolean cannot +carry that, and encoding it inline would force every server and client to agree +on a regulatory taxonomy. This scheme lets a server that already knows the +classification (a healthcare record store, a payments API) attach it as evidence, +while a client that does not implement the scheme still sees `sensitive: true`. + +## Specification + +### Scheme identity + +A `data-class.v1` record is selected by `evidenceRef.type == "data-class.v1"` on +a `trust-annotations` annotation whose `sensitive` is `true`. The +`digest`/`canonicalization` pair over the record is required exactly as for any +other scheme. + +### Payload (skeleton) + +The record is a JSON object. Shapes below are **open questions**, not settled: + +```json +{ + "class": "confidential", + "regulatory": ["hipaa"], + "labels": ["com.example.pii.ssn"], + "policyRef": "https://policy.example.com/classes/confidential" +} +``` + +- `class` — a coarse level. Candidate set `public | internal | confidential | + restricted` (four levels, from the original SEP-1913 taxonomy). Whether the set + is fixed or registry-curated is open. +- `regulatory` — zero or more regulatory scopes the result falls under. Open + strings, not an enum (so a new regime doesn't need a schema change). This is + the `:scope` half of @krubenok's `confidential:hipaa`. +- `labels` — optional org-defined tags, reverse-DNS namespaced per @Mossaka, for + vocabularies a deployment defines for itself. +- `policyRef` — optional pointer to the policy that defines the classes, so the + record is interpretable by a host that hasn't pre-agreed the vocabulary. + +### Graceful degradation + +A client that does not implement `data-class.v1` ignores the record and relies on +the `trust-annotations` `sensitive` boolean, which remains meaningful on its own. +The scheme only ever *refines* the boolean; it never contradicts it (a +`data-class.v1` record only appears where `sensitive` is already `true`). + +## Producer / consumer + +- **Producer (candidate).** A server fronting a regulated store (health records, + payments) that already classifies its data internally. +- **Consumer (candidate).** A host policy engine that maps `class` + `regulatory` + to a control (block, redact, prompt). The same host-side resolution model as + the FIDES scheme applies: the wire marker is advisory; the regulated semantics + are host-resolved against the deployment's policy. + +## Open questions + +- Is the `class` set fixed (`public/internal/confidential/restricted`) or + registry-curated? @localden's removability concern argues against fixing it. +- Do `regulatory` and `labels` overlap enough to collapse into one open-string + list, or are "named regime" and "org-defined tag" usefully distinct? +- Should `data-class.v1` ever be expressible **on the wire** as a structured + escape hatch (tracked in [open-questions.md](../docs/open-questions.md)), + or is keeping it strictly behind `evidenceRef` the right boundary? +- How does this relate to SEP-2061's `DataClass` / `RegulatoryScope` — is this + scheme the migration target for that work, or a parallel encoding? + +## Changelog + +- **2026-06-17** — Initial skeleton. Payload shapes are candidates pending the + open questions above.