diff --git a/spec-core.md b/spec-core.md index 1cc191403..8c035f0b2 100644 --- a/spec-core.md +++ b/spec-core.md @@ -49,8 +49,11 @@ Sections 4-8 define the protocol surfaces that implementations evaluate independ | [Client ID Metadata Documents](https://datatracker.ietf.org/doc/draft-ietf-oauth-client-id-metadata-document/) (CIMD, IETF OAuth WG draft) | A client identifier that is itself an `https` URL the authorization server fetches to obtain RFC 7591-shaped client metadata, with no prior registration handshake. Control of the URL's domain is the trust root. CIMD is how deployed MCP clients present themselves: the MCP authorization specification revision 2025-11-25 states that authorization servers and clients SHOULD support CIMD and MAY support RFC 7591 dynamic client registration, which is retained for backward compatibility. Core treats a validated CIMD document as one source of validated binding metadata (Section 6) and its verified domain as a trust signal; the fetch and validation obligations belong to the OAuth binding rather than to Core. | | [SMART on FHIR](https://hl7.org/fhir/smart-app-launch/) | Follows the domain-profile-over-OAuth pattern PDPP adopts: OAuth handles authorization, and the profile adds a domain data model, consent semantics, and a conformance regime. SMART on FHIR reached ubiquity through regulatory adoption of SMART-on-FHIR-patterned API requirements (the ONC Cures Act rule). | | [UK Open Banking](https://www.openbanking.org.uk/standards/) | Also follows the domain-profile-over-OAuth pattern PDPP adopts: OAuth handles authorization, and the profile adds a domain data model, consent semantics, and a conformance regime. UK Open Banking reached ubiquity through the CMA's Open Banking mandate for the largest UK banks. | -| [UMA 2.0](https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-grant-2.0.html) (Kantara) | UMA is important prior art for PDPP's user-managed, standing, revocable access model, particularly where an outside party seeks access to user-controlled resources. PDPP's authorization protocol derives directly from OAuth 2.0 and RFC 9396. | +| [UMA 2.0](https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-grant-2.0.html) (Kantara) | UMA is important prior art for PDPP's user-managed, standing, revocable access model, particularly where an outside party seeks access to user-controlled resources. PDPP's authorization protocol derives directly from OAuth 2.0 and RFC 9396. UMA Section 6.1 places the setting of the resource owner's policy conditions outside its scope. PDPP's structured commitments are therefore a deliberate addition rather than a divergence. | | [GNAP](https://www.rfc-editor.org/rfc/rfc9635) (RFC 9635) | GNAP is an IETF authorization protocol that revisits OAuth-style delegation with a new protocol design. Several design decisions are directly relevant to PDPP: (1) interaction modes beyond browser redirects (relevant to nonstandard authorization interaction patterns); (2) request continuation for multi-step consent negotiation (relevant to optional streams); (3) key-bound grants instead of bearer tokens (stronger security for ongoing personal data access); (4) built-in grant management with revocation and rotation (relevant to `continuous` access mode). PDPP v0.1 uses OAuth 2.0 + RFC 9396. A future version should evaluate whether GNAP is a better foundation. PDPP's entity-scoped `client_display` already follows GNAP's pattern of carrying client display metadata inline in the request. For key-bound tokens specifically, DPoP (RFC 9449) offers an OAuth-native path to GNAP-style sender-constrained tokens and is a candidate optional hardening profile for v0.2. | +| [IEEE 7012-2025](https://standards.ieee.org/ieee/7012/7192/) (MyTerms) | Under IEEE 7012-2025 the individual proffers privacy terms as the first party, and both sides keep a matching record. A PDPP grant records an authorization rather than an agreement, and a future version could let it reference an agreement identifier. | +| [ISO/IEC TS 27560:2023](https://www.iso.org/standard/80392.html) | ISO/IEC TS 27560 specifies an information structure for consent records and receipts, organised as header, processing, parties, and event sections. A PDPP grant already carries most of that structure. It records a reference to the notice presented at consent only where the authorization server displayed a client policy or terms link. An export mapping from the grant to a 27560 record is deferred to a companion document and is not a v0.1 conformance requirement. Such a mapping would express the record in the W3C Data Privacy Vocabulary, which keeps purpose, consent, and the consent record as distinct classes as PDPP does, and whose consent record references a notice object rather than a bare URL. DPV is a Community Group report and is not a W3C standard. | +| [ISO/IEC 29184:2020](https://www.iso.org/standard/70331.html) | ISO/IEC 29184 requires an organization to keep the version of the notice presented when consent was given. PDPP requires the authorization server to record the client policy and terms links it displayed. Core points deployments at retaining a snapshot or digest as the stronger bar this standard sets. Retention of third-party document contents is a deployment choice rather than an authorization semantic. | | [Solid](https://solidproject.org) | Solid takes the full re-architecture approach: personal data moves into user-controlled pods with RDF/Linked Data semantics, which requires source platforms to adopt the model or users to migrate off-platform. PDPP instead layers on existing OAuth infrastructure and bootstraps data supply through the Collection Profile, without requiring source platforms to adopt anything. | | [Data Transfer Project](https://github.com/dtinit/data-transfer-project) (DTI) | PDPP and DTI are complementary. The Data Transfer Project handles transfer mechanics, and DTI's stated position is that there is "no silver bullet" for portability: multiple approaches coexist. DTI's Data Trust Registry (post-pilot, 2026) addresses who is trusted: it vets services seeking access to platforms' portability interfaces so that platforms can rely on shared trust signals. PDPP addresses what was consented and how it is enforced (the grant and the resource server interface); a trust registry and PDPP's consent semantics compose rather than compete. The two protocols can chain. See Appendix B. | | [Airbyte](https://airbyte.com) / [Singer](https://www.singer.io) | PDPP borrows the RECORD/STATE checkpoint pattern for incremental sync. This record and state-checkpoint lineage informs the Collection Profile companion specification; it appears here for reader orientation and is informative for Core. | @@ -705,7 +708,7 @@ For PDPP Core v0.1 interoperability, a conforming authorization server MUST acce 1. The AS MUST resolve requester identity metadata from the best available source. Source precedence is local registration or trust-registry metadata, then validated software-statement metadata if supported, then validated binding metadata, then inline `client_display`, then `client_id` fallback. 2. If the resolved metadata contains a display name, the AS MUST display it to the user during consent. If no display name is available, the AS MUST display `client_id` as the requester identity. -3. If the resolved metadata contains `policy_uri` or `tos_uri`, the AS MAY display them as secondary links or disclosures. +3. If the resolved metadata contains `policy_uri` or `tos_uri`, the AS SHOULD display them during consent, and MUST record the exact values it displayed in the issued grant's `client.client_display`. A value the AS resolved but did not display MUST NOT be recorded as displayed. RFC 7591 Section 2 already states the authorization server SHOULD display each of these URLs to the end user when provided, so the display obligation here is that of the metadata vocabulary PDPP reuses, not an additional one. A recorded URI establishes which policy and terms documents the owner was pointed at, not what those documents said. The target is under the client's control and can change after issuance. Deployments that need the stronger evidence SHOULD retain a snapshot or content digest of the documents alongside the grant. That is the bar ISO/IEC 29184:2020 Section 5.2.8 sets, requiring an organization to keep the version of the notice presented when consent was given. Core does not mandate that retention in v0.1. It would oblige the AS to fetch and store third-party documents, which is a deployment cost and a new fetch surface rather than an authorization semantic. 4. If the server has a positive trust signal for the client (e.g., verified domain control, trust registry membership), it MUST render that status distinctly (e.g., a "verified" badge). If it has no positive trust signal, it MUST treat the client as unverified and SHOULD display an "unverified app" indicator. 5. **Domain control as a trust signal.** The binding may identify a client by a URL that client controls. Where the AS both retrieved that client's metadata from that URL over HTTPS and confirmed the retrieved document identifies the same client, the AS has verified that the client controls that domain. The AS MAY treat verified domain control as a positive trust signal under obligation 4, and when it does it MUST name the verified domain rather than assert an unqualified verification (for example "Verified domain: example.com", not "Verified app"). Domain control establishes only that the operator of that domain published this client's metadata. It is not an assertion about the client's conduct, its data practices, or any review by the AS operator, and the AS MUST NOT present it as one. 6. The AS MUST treat `logo_uri` as untrusted content until it has been accepted under local policy. It MUST NOT fetch and render a client-supplied remote logo in the consent UI unless the client is verified or the asset has been proxied, cached, and approved under local policy. For unverified clients, the AS SHOULD generate a monogram from the resolved display name. @@ -773,6 +776,8 @@ A selection request does not carry `source.kind`. The authorization server deriv The AS MUST obtain explicit affirmative user consent before issuing any grant with `purpose_code` value `https://pdpp.dev/purpose/ai_training`. This is the sole purpose code with a mandatory consent requirement at the protocol level. +Resolved requester identity metadata for such a request MUST contain `policy_uri`, and the AS MUST reject the request when it does not. Consent to training on personal data cannot be informed without somewhere to read how the recipient handles that data, and this is the one purpose where Core already treats consent as protocol-enforced rather than advisory. The obligation is on the resolved metadata, not on inline `client_display`, so a client whose `policy_uri` is already known to the AS through registration or a validated binding does not have to repeat it in the request. + ### Stream selection parameters Per-stream, within the `streams` array. All are optional except `name`. @@ -871,7 +876,7 @@ The authorization server issues an access token bound to the grant. The client u | `grant_id` | string | yes | Protocol metadata | Unique identifier. | | `issued_at` | ISO 8601 | yes | Protocol metadata | When the grant was issued. | | `subject` | object | yes | Identity binding | Exactly `{ id }`. The `subject.id` is an opaque string, unique within the issuing AS's namespace. No format constraint is imposed. | -| `client` | object | yes | Identity binding | Exactly `{ client_id }` or `{ client_id, client_display }`. `client_display`, when retained, is the requester identity metadata resolved by the AS, not unverified inline input. | +| `client` | object | yes | Identity binding | Exactly `{ client_id }` or `{ client_id, client_display }`. `client_display`, when retained, is the requester identity metadata resolved by the AS, not unverified inline input. Where the AS displayed `policy_uri` or `tos_uri` during consent, `client_display` MUST carry the exact displayed values (see [Client display metadata](#client-display), obligation 3). | | `source` | object | yes | Protocol-enforced | Exact `{ kind, id }` retained from the accepted SourceDeclaration. `id` is authorization identity; `kind` is provenance metadata. | | `source_declaration` | object | yes | Protocol evidence | `{ version }` records the opaque revision of the exact declaration snapshot used for consent and issuance. It is evidence metadata, not a live lookup authority. | | `purpose_code` | URI | yes | Structured policy declaration | Machine-readable purpose (see Appendix A). | @@ -1477,14 +1482,14 @@ A conformant authorization server: 4. Expands wildcards and selection presets into explicit stream names, fields, per-stream instance handles, resources, and frozen time constraints before issuing the grant. 5. Produces a binding-neutral Source validation failure when a request contains both or neither of `streams` and `selection_preset`. The OAuth/RAR binding maps it to RFC 9396 `invalid_authorization_details`. 6. MUST NOT reject a `purpose_code` solely because it is not in the PDPP registry. For unrecognized codes, displays `purpose_description` if present, or the raw URI. MAY reject a `purpose_code` based on local policy. -7. Renders requester identity metadata, declaration-authored data descriptions, structured policy declarations, and client-authored claims as semantically distinct categories during consent. MUST attribute `client_claims` to the client and MUST NOT present them as protocol-enforced terms. If `client_claims` are rendered during final review, binds the normalized exact claims into the immutable final approval artifact and review revision, and preserves that binding in retained consent evidence, without adding them to the resolved grant or RS enforcement. +7. Renders requester identity metadata, declaration-authored data descriptions, structured policy declarations, and client-authored claims as semantically distinct categories during consent. MUST attribute `client_claims` to the client and MUST NOT present them as protocol-enforced terms. If `client_claims` are rendered during final review, binds the normalized exact claims into the immutable final approval artifact and review revision, and preserves that binding in retained consent evidence, without adding them to the resolved grant or RS enforcement. Records in the issued grant's `client.client_display` the exact `policy_uri` and `tos_uri` values it displayed during consent. 8. Tracks grant lifecycle (active, expired, revoked). Reflects revocation immediately in introspection responses (`active: false`). 9. Issues access tokens bound to specific grants. Access tokens include the PDPP introspection extension fields. 10. For `single_use` grants, consumes the grant atomically with first client-token issuance and rejects subsequent attempts to issue new client access tokens against that grant. 11. Validates stream/field/view/resource-id shape at grant issuance. 12. MUST NOT define a view including fields absent from the retained SourceDeclaration schema. 13. Resolves view names to field lists at issuance time; stores resolved `fields` in the `StreamGrant`. Client-token record reads reject query-time `view` in v0.1. Owner-token current-capability reads MAY resolve current views. -14. Obtains explicit affirmative user consent before issuing grants with `purpose_code: "https://pdpp.dev/purpose/ai_training"`. +14. Obtains explicit affirmative user consent before issuing grants with `purpose_code: "https://pdpp.dev/purpose/ai_training"`, and rejects such a request when the resolved requester identity metadata has no `policy_uri`. 15. Resolves omitted instance IDs before the final approval surface. Binds exact resolved instances and all final decision fields to an immutable review revision or digest. Rejects stale approval if eligibility or the @@ -1902,7 +1907,7 @@ Purpose codes are URIs. The following codes are defined by PDPP. Implementers ma | `https://pdpp.dev/purpose/analytics` | Analyzing user data to produce insights for the user. | | `https://pdpp.dev/purpose/export` | Exporting data for the user's own use. | | `https://pdpp.dev/purpose/agent_context` | Providing context to a personal AI agent. | -| `https://pdpp.dev/purpose/ai_training` | Using data to train AI models. The AS MUST obtain explicit affirmative user consent before issuing any grant with this purpose code. This is a protocol-level requirement, not merely advisory. | +| `https://pdpp.dev/purpose/ai_training` | Using data to train AI models. The AS MUST obtain explicit affirmative user consent before issuing any grant with this purpose code, and the resolved requester identity metadata MUST contain `policy_uri`. These are protocol-level requirements, not merely advisory. See [AI training consent](#ai-training-consent). | | `https://pdpp.dev/purpose/research` | Academic or market research. | --- diff --git a/spec-deferred.md b/spec-deferred.md index 1f72b9093..4565c2867 100644 --- a/spec-deferred.md +++ b/spec-deferred.md @@ -195,10 +195,28 @@ _Newly deferred (2026-09-02; raised in the 2026-08-19 working session)._ **Why it is open:** The protocol has no representation of who the client is as a legal entity, and no event by which a change of control could reach an issued grant. One suggestion from the session was to require clients to declare ownership type. Whether that belongs in the protocol, in the conformance programme, or nowhere is undecided, as is whether a change of control should force revocation, force re-consent, or merely be disclosed. -**Related:** ISO MyTerms was raised in the same discussion as prior art for owner-specified terms under which a first party holds data. It has not been evaluated for fit, and whether owner-specified terms belong in Core, in a companion RFC with the authorization server holding templates, or outside PDPP entirely is itself open. +**Related:** MyTerms was raised in the same discussion as prior art for owner-specified terms under which a first party holds data. It is IEEE 7012-2025, "Standard for Machine Readable Personal Privacy Terms." Earlier notes in this repository called it "ISO MyTerms," which is wrong on both the body and the status. Whether owner-specified terms belong in Core, in a companion RFC with the authorization server holding templates, or outside PDPP entirely is still open. See [MyTerms (IEEE 7012) compatibility](#myterms-ieee-7012-compatibility) for how a PDPP grant relates to that model. **v0.1 posture:** Out of scope. `client_claims` carries client-authored, explicitly non-enforceable statements about a specific request; it is not an ownership record and must not be read as one. +### MyTerms (IEEE 7012) compatibility + +_Newly deferred (2026-09-03); written in response to the question of whether PDPP risks drifting from MyTerms._ + +**Description:** IEEE 7012-2025 "Standard for Machine Readable Personal Privacy Terms," known as MyTerms, inverts the usual direction of an online agreement. The individual is the first party and proffers privacy terms. The service provider is the second party and accepts one of them. The terms are not invented per relationship. They are chosen from a roster kept by a neutral non-business entity, which today is Customer Commons. Each rostered term is a versioned dereferenceable URL such as `https://customercommons.org/agreements/p2b1/0-9/`. Agreements are recorded and kept by both sides. + +**How a PDPP grant relates:** A PDPP grant records an authorization, not an agreement, and the difference matters. The grant is immutable, it names the second party (`client`), and it carries the recipient-side commitments as structured fields rather than prose. `purpose_code` and `purpose_description` state what the data may be used for. `retention` states how long it may be kept and what happens at expiry. `access_mode` bounds whether the access is one-shot or ongoing. So the grant holds most of what an agreement record would need, and a future version could let it reference an agreement that the owner proffered. Calling every grant an agreement record today would overstate it. `client_claims` is not part of this analogy. It is client-authored and non-enforceable, which is the one-sided posture MyTerms exists to displace, so it must not be read as an agreed term. Two structural gaps remain. MyTerms expects both sides to hold a matching record, and PDPP defines only the authorization server's copy. MyTerms permits the second party to counter-offer, and a PDPP grant is issued after consent rather than negotiated within the protocol. + +**What would create incompatibility:** Inventing a PDPP terms vocabulary of our own. If PDPP mints its own names for terms that a roster already identifies, then two records of the same real-world agreement become machine-incomparable across deployments. That is the exact failure the roster model exists to prevent. PDPP therefore defines no terms vocabulary and should continue not to. + +**The shape a future version should take:** The design worth recording is two-sided, because a one-sided record is what MyTerms rejects. The client publishes, in its client metadata document, the rostered terms it accepts. The authorization server holds the rostered term the owner chose, from the IEEE 7012 roster kept by Customer Commons. At grant time the authorization server matches the two mechanically, without a negotiation round trip. The grant then records the matched term in an optional `agreement` object, carrying the term URI, its version, and the acceptance time. Introspection echoes that object so the resource server and the client read back the same agreement the owner saw. PDPP defines none of this in v0.1 and defines no terms vocabulary of its own at any version. The roster is small, the format for the second party's copy is unsettled, and no client publishes accepted terms today. + +**Why the carrier has to be designed, not improvised:** RFC 9396 Section 5 requires the authorization server to reject an `authorization_details` object of known type that carries unknown fields. So a request-side carrier for terms cannot be added incrementally by clients. It must be defined in the `https://pdpp.dev/data-access` type itself when that version arrives. The grant-side and metadata-side halves above carry no such constraint, which is why the request side is the part that needs a version to land in. + +**Do not route agreements through `purpose_code`:** A rostered agreement URI is a syntactically valid `purpose_code`, so this route is legal today and still wrong. Purpose and agreement are separate objects in every standard surveyed. The `ai_training` consent rule switches on the purpose code's value, and an agreement URI in that field would defeat it. + +**v0.1 posture:** Informative. No Core change. Nothing in v0.1 forecloses the design above, and Section 1 records the relationship to IEEE 7012, ISO/IEC TS 27560, and ISO/IEC 29184. + ### Bulk export as a distinct access path _Newly deferred (2026-09-02; raised in the 2026-08-19 working session)._