From b4f679547a8388a6a7d7d332b4bbd2badabfaf92 Mon Sep 17 00:00:00 2001 From: Tim Nunamaker Date: Thu, 10 Sep 2026 17:12:32 -0500 Subject: [PATCH 1/4] spec(deferred): name MyTerms correctly and say how a grant relates to it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two entries in spec-deferred.md called this prior art "ISO MyTerms." It is not an ISO standard. It is IEEE P7012, published in January 2026 as IEEE 7012-2025, "Standard for Machine Readable Personal Privacy Terms." Leaving the wrong name in a normative-adjacent document sends a reader looking for a standard that does not exist, and it hid the fact that the thing is now published rather than a draft we could ignore. The deeper gap was that the entry said MyTerms "has not been evaluated for fit," which left open whether PDPP was quietly drifting into an incompatibility. This adds an informative entry that does the evaluation. MyTerms inverts the usual direction of an online agreement: the individual is the first party and offers privacy terms, and the service provider is the second party that accepts one. The terms are not written per relationship — they are picked from a roster kept by a neutral non-business entity (today Customer Commons), where each term is a versioned dereferenceable URL. Against that model a PDPP grant is already the recorded agreement on the owner's side: it is immutable, it names the second party, and it carries the recipient-side commitments as structured fields (purpose_code, retention, access_mode) rather than prose. The entry states the two places the analogy breaks — MyTerms expects both sides to hold a record where PDPP defines only the authorization server's copy, and MyTerms allows a counter-offer where a PDPP grant is issued after consent rather than negotiated — so a later reader does not overclaim the fit. It also names the thing that would actually cause incompatibility: inventing a PDPP-specific vocabulary for terms a roster already names. We do not have that problem today, because purpose_code is an absolute URI the authorization server must accept even when it does not recognize it, so a rostered term is already expressible with no schema change. That is the positive path, and keeping purpose_code open is what preserves it. No Core change and no v0.1 commitment: the roster is small and the second-party record format is unsettled, so this records the analysis and the hedge rather than a dependency. The same wrong name also appears twice in the 2026-08-20 working-session notes. Those are left alone deliberately — they are a dated record of what was said in the room, not a statement of fact about the standard. Assisted-by: AI Signed-off-by: Tim Nunamaker --- spec-deferred.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/spec-deferred.md b/spec-deferred.md index 1f72b9093..e9ecfc2cb 100644 --- a/spec-deferred.md +++ b/spec-deferred.md @@ -195,10 +195,24 @@ _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 P7012, published as IEEE 7012-2025 "Standard for Machine Readable Personal Privacy Terms"; earlier notes in this repository called it "ISO MyTerms," which is wrong. 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 P7012) compatibility](#myterms-ieee-p7012-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 P7012) 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 online agreement: the individual is the first party and proffers privacy terms, and the service provider is the second party that 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, and 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 is already the recorded agreement on the owner's side. It 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` are what the data may be used for, `retention` is how long it may be kept and what happens at expiry, and `access_mode` bounds whether the access is one-shot or ongoing. `client_claims` is not part of this analogy: it is explicitly client-authored and non-enforceable, which is the one-sided privacy-policy 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 record, and PDPP defines only the authorization server's copy. MyTerms allows the second party to counter-offer before agreement, and a PDPP grant is issued after consent rather than negotiated within the protocol. + +**What would create incompatibility:** Inventing a PDPP-specific vocabulary for terms that a roster already names. If PDPP grows a closed enum or a bespoke free-text scheme for purpose and retention semantics, then two grants expressing the same real-world terms become machine-incomparable across deployments, which is the exact failure the roster model exists to prevent. PDPP does not have that problem today because `purpose_code` is an absolute URI the AS MUST accept without recognizing it, so an external identifier is already expressible. + +**Positive path:** A grant MAY carry a rostered MyTerms agreement identifier as its `purpose_code`, or alongside it, without any schema change, because a rostered term is already a dereferenceable URI and `purpose_code` already accepts one. The W3C Data Privacy Vocabulary community group publishes an "Extension for IEEE P7012" that models the same objects PDPP would need to bridge — `Agreement`, `AgreementRegistry`, and `AgreementInteractionRecord` — and recommends ODRL for expressing term content, so a mapping has somewhere to land rather than needing to be invented. The cheap hedge is therefore to reference rostered terms rather than mint our own vocabulary, and to keep `purpose_code` open to unrecognized URIs. + +**v0.1 posture:** Informative. No Core change. Nothing in v0.1 forecloses a later `terms_ref` field or a MyTerms profile, and the roster is currently too small and the second-party record format too unsettled to depend on. + ### Bulk export as a distinct access path _Newly deferred (2026-09-02; raised in the 2026-08-19 working session)._ From 5bd8436b2241f3e71a3d82dfa17108addec170e7 Mon Sep 17 00:00:00 2001 From: Tim Nunamaker Date: Thu, 10 Sep 2026 17:12:32 -0500 Subject: [PATCH 2/4] spec(core): display client policy and terms links, and record what was shown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An owner approving a PDPP grant may be shown the requesting application's privacy policy and terms-of-service links, or may not be. Core left both halves of that soft. It said the authorization server "MAY display them as secondary links," and it never required the server to keep any trace of which links it put in front of the owner. So an owner who later disputes what a company was allowed to do with their data has no record of the terms they were pointed at when they agreed, and the server has no way to show one. Two changes, and the first is smaller than it looks. RFC 7591 Section 2 — the OAuth client-registration metadata vocabulary that Core already borrows `policy_uri` and `tos_uri` from — says of each field that "the authorization server SHOULD display this URL to the end-user if it is provided." Core's MAY was therefore weaker than the source it cites, which was a drafting slip rather than a decision. Raising it to SHOULD restores the strength the borrowed vocabulary already carries. The second change is a real addition: where the server displayed either link, the issued grant MUST carry the exact displayed values in `client.client_display`. This needs no new field. The grant schema already has an optional `client_display` holding server-resolved requester identity metadata, with `policy_uri` and `tos_uri` among its members — it was simply never obligatory to populate them. The rule also says a value the server resolved but did not show MUST NOT be recorded as displayed, so the record stays a record of the consent surface rather than of the server's internal lookup. That evidence is deliberately bounded, and the text now says so rather than overselling it. A recorded URI shows which documents the owner was pointed at, not what those documents said, because the target belongs to the client and can change after issuance. ISO/IEC 29184:2020 Section 5.2.8 — the ISO standard on online privacy notices and consent — sets the stronger bar, requiring that an organization "shall keep and make available the version of the notice presented when the PII principal gave consent." Core points deployments at that as a SHOULD instead of mandating it, because retaining the version means fetching and storing third-party documents: a real deployment cost and a new outbound-fetch surface, neither of which is an authorization semantic. Separately, a client requesting the `ai_training` purpose must now have a `policy_uri` in its resolved metadata, and the server must reject the request otherwise. Training on someone's personal data is already the one purpose code where Core treats consent as protocol-enforced rather than advisory, and consent to it is not informed if there is nowhere to read how the recipient handles the data. The requirement is on the resolved metadata, not on the inline request, so a client the server already knows through registration or a validated binding does not have to resend it. Confidence is uneven across the three and worth flagging for review. The SHOULD-display realignment is near-certain — it is what the cited RFC says. The recording obligation is well-precedented in the consent-receipt lineage (ISO/IEC 29184, Kantara Consent Receipt) but has no precedent in the OAuth or OpenID Connect family, so it is a genuine extension of that lineage rather than a gap-fill. The `ai_training` policy_uri rule is the weakest of the three: no regime found names AI training as a trigger for a heightened privacy-policy requirement, so it rests on Core's own existing decision to single that purpose out, not on outside prior art. Verified: `pnpm spec:check`, which regenerates the site's spec pages from these root files and fails on any drift between them, passes. `pnpm spec:dates` fails only on spec-reference-implementation-examples.md, a file this branch does not touch and which was already failing on origin/main. No reference-implementation code changes here; the consent card in packages/operator-ui renders neither link today, so the SHOULD-display rule describes work that surface has not done yet. Assisted-by: AI Signed-off-by: Tim Nunamaker --- spec-core.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/spec-core.md b/spec-core.md index 1cc191403..b1dab325f 100644 --- a/spec-core.md +++ b/spec-core.md @@ -705,7 +705,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, which is what ISO/IEC 29184:2020 Section 5.2.8 requires when it says the organization "shall keep and make available the version of the notice presented when the PII principal gave consent." Core does not mandate that retention in v0.1 because it obliges 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 +773,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 +873,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 +1479,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 +1904,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. | --- From deb6b81e5f3fe6130570d7780058b87d8e366f3a Mon Sep 17 00:00:00 2001 From: Tim Nunamaker Date: Thu, 10 Sep 2026 17:12:32 -0500 Subject: [PATCH 3/4] spec: relate Core to the agreement and consent-record standards, S1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An independent judge reviewed the two stances on offer for terms support and chose S1 over S2 (disagreeing with the research's own S2 recommendation at 82/100 confidence). S2 would have added an optional `agreement` object to the grant now. The judge's decisive reason: the argument for adding it early rested on RFC 9396 Section 5, which constrains what a *client* may send in an authorization request, while the proposed field was grant-side only. So Section 5 neither forces nor eases that field, and adding it would standardize a record shape before the flow that produces it exists — there is no client publishing accepted terms, no publication surface, and no acceptance step anywhere today. This is S1: say precisely how PDPP relates to the standards in question, and record the design a future version should implement, without inventing fields for it now. Section 1 gains four relationship rows. IEEE 7012-2025 (MyTerms) says a PDPP grant records an authorization and could later reference an agreement; it deliberately stops short of calling every grant an agreement record, which would overstate what the grant is. W3C DPV 2.3 is named for its consent-record vocabulary, and its extension for IEEE 7012 is described as live — it ships in DPV 2.3 as `STANDARD-IEEE-7012`, which corrects an earlier claim that the extension had been stranded at an old draft; the row keeps the caveat that DPV is a Community Group report and not a W3C standard. ISO/IEC TS 27560 is named as a deferred export mapping, and says PDPP records a notice reference only where a link was actually displayed, rather than claiming every grant carries 27560's mandatory notice field. ISO/IEC 29184 is kept as written, because it is the citation that explains why a recorded URI is weaker evidence than a retained version. ODRL was proposed as a fifth row and is deliberately omitted: the mapping is speculative and no v0.1 field depends on it. The UMA row gains one clause noting that UMA puts the resource owner's policy outside its own scope, which is why PDPP's structured commitments are an addition rather than a divergence. The deferred MyTerms entry drops the `purpose_code` route it previously offered as the positive path, and now warns against it: an agreement URI is a syntactically valid purpose code, so the route is legal and still wrong, because purpose and agreement are separate objects everywhere and the `ai_training` rule switches on the purpose code's value. In its place the entry records the two-sided design a future version should implement. The client publishes the rostered terms it accepts in its client metadata document. The authorization server holds the rostered term the owner chose from the IEEE 7012 roster. At grant time the server matches the two mechanically, with no negotiation round trip. The grant records the matched term — URI, version, acceptance time — in a future optional `agreement` object that introspection echoes. PDPP defines no terms vocabulary of its own, at this version or any later one; that is the thing that would create incompatibility with a roster-based standard. The entry also records why the request side is the half that needs a version to land in: RFC 9396 Section 5 requires the authorization server to reject an authorization details object of known type carrying unknown fields, so a request-side carrier cannot be adopted incrementally by clients and must be defined in the `https://pdpp.dev/data-access` type when that version arrives. The grant-side and metadata-side halves carry no such constraint. The client `policy_uri`/`tos_uri` display-and-record change from the earlier commits on this branch is unchanged. Verified: `pnpm spec:check` passes; `pnpm spec:dates` passes (the unrelated stale-date failure this branch reported earlier was fixed on main); and the spec prose gate, which merged into main after the earlier commits here, now reports no new findings against a merge-base baseline. That last one also required rewriting four over-long sentences this branch had itself introduced before the gate existed. Assisted-by: AI Signed-off-by: Tim Nunamaker --- spec-core.md | 8 ++++++-- spec-deferred.md | 18 +++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/spec-core.md b/spec-core.md index b1dab325f..b3aaed339 100644 --- a/spec-core.md +++ b/spec-core.md @@ -49,8 +49,12 @@ 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) | IEEE 7012-2025 inverts the usual direction of an online agreement. The individual is the first party and proffers privacy terms chosen from a roster kept by a neutral non-business entity, and both sides keep a matching record. A PDPP grant records an authorization, not an agreement, and carries recipient commitments as structured fields rather than prose. A future version could let a grant reference an agreement identifier; v0.1 defines no such field. PDPP does not claim conformance. The standard expects both parties to hold a record and permits a counter-offer, where PDPP defines one record and issues it after consent. | +| [W3C DPV 2.3](https://w3id.org/dpv) | The Data Privacy Vocabulary supplies consent-record terms that PDPP's structured policy declarations correspond to. It keeps purpose, consent, and the consent record as distinct classes, as PDPP does. Its consent record references a notice object rather than a bare URL. That is why PDPP states plainly that a recorded URI identifies which document was shown, not what it said. DPV 2.3 carries a live extension for IEEE 7012-2025, `STANDARD-IEEE-7012`, which names the `Agreement` and `AgreementRegistry` concepts a future PDPP terms mapping would target. DPV is a Community Group report and is not a W3C standard. | +| [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. It is 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. It is not a v0.1 conformance requirement. | +| [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 +709,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 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, which is what ISO/IEC 29184:2020 Section 5.2.8 requires when it says the organization "shall keep and make available the version of the notice presented when the PII principal gave consent." Core does not mandate that retention in v0.1 because it obliges the AS to fetch and store third-party documents, which is a deployment cost and a new fetch surface rather than an authorization semantic. +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. diff --git a/spec-deferred.md b/spec-deferred.md index e9ecfc2cb..ac5084f20 100644 --- a/spec-deferred.md +++ b/spec-deferred.md @@ -195,23 +195,27 @@ _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:** MyTerms was raised in the same discussion as prior art for owner-specified terms under which a first party holds data. It is IEEE P7012, published as IEEE 7012-2025 "Standard for Machine Readable Personal Privacy Terms"; earlier notes in this repository called it "ISO MyTerms," which is wrong. 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 P7012) compatibility](#myterms-ieee-p7012-compatibility) for how a PDPP grant relates to that model. +**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 P7012) compatibility +### 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 online agreement: the individual is the first party and proffers privacy terms, and the service provider is the second party that 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, and 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. +**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 is already the recorded agreement on the owner's side. It 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` are what the data may be used for, `retention` is how long it may be kept and what happens at expiry, and `access_mode` bounds whether the access is one-shot or ongoing. `client_claims` is not part of this analogy: it is explicitly client-authored and non-enforceable, which is the one-sided privacy-policy 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 record, and PDPP defines only the authorization server's copy. MyTerms allows the second party to counter-offer before agreement, and a PDPP grant is issued after consent rather than negotiated within the protocol. +**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-specific vocabulary for terms that a roster already names. If PDPP grows a closed enum or a bespoke free-text scheme for purpose and retention semantics, then two grants expressing the same real-world terms become machine-incomparable across deployments, which is the exact failure the roster model exists to prevent. PDPP does not have that problem today because `purpose_code` is an absolute URI the AS MUST accept without recognizing it, so an external identifier is already expressible. +**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. -**Positive path:** A grant MAY carry a rostered MyTerms agreement identifier as its `purpose_code`, or alongside it, without any schema change, because a rostered term is already a dereferenceable URI and `purpose_code` already accepts one. The W3C Data Privacy Vocabulary community group publishes an "Extension for IEEE P7012" that models the same objects PDPP would need to bridge — `Agreement`, `AgreementRegistry`, and `AgreementInteractionRecord` — and recommends ODRL for expressing term content, so a mapping has somewhere to land rather than needing to be invented. The cheap hedge is therefore to reference rostered terms rather than mint our own vocabulary, and to keep `purpose_code` open to unrecognized URIs. +**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. -**v0.1 posture:** Informative. No Core change. Nothing in v0.1 forecloses a later `terms_ref` field or a MyTerms profile, and the roster is currently too small and the second-party record format too unsettled to depend on. +**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, DPV, ISO/IEC TS 27560, and ISO/IEC 29184. ### Bulk export as a distinct access path From 128d32ef1950451c081301069faf59917cafe54e Mon Sep 17 00:00:00 2001 From: Tim Nunamaker Date: Thu, 10 Sep 2026 17:12:32 -0500 Subject: [PATCH 4/4] spec(core): keep three standards rows, not four MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Applying a weight test to the rows this branch added: a row in Section 1's standards table earns its place only if it explains something the spec does today, or names a bar the spec is measured against. A row that is merely adjacent and interesting is table weight without a reader benefit. Four rows went in; three survive that test. ISO/IEC 29184 stays as written. It is the reason Core records what was displayed rather than treating a bare URI as sufficient evidence, so it explains a rule the spec already carries. ISO/IEC TS 27560 stays as the deferred consent-record mapping, and now absorbs what the separate DPV row was carrying. The Data Privacy Vocabulary did not describe anything Core does today: it is the vocabulary such a mapping would be expressed in, which makes it a detail of the 27560 row rather than a relationship of its own. Naming it inside that row keeps the useful part — DPV keeps purpose, consent, and the consent record as distinct classes the way PDPP does, and its consent record points at a notice object rather than a bare URL — and keeps the caveat that DPV is a Community Group report and not a W3C standard. The separate row is dropped. IEEE 7012 shrinks to the two short sentences that carry the load: the individual proffers terms as the first party and both sides keep a matching record, and a PDPP grant records an authorization rather than an agreement and could later reference one. The conformance disclaimer and the counter-offer detail move out of the table; the deferred entry in spec-deferred.md already states both at length, and repeating them in a one-line-per-cell table was duplication rather than emphasis. The row is worth keeping at this size because the question it answers came out of workshop feedback, so a reader arriving at the table will look for it. ODRL is not added. It describes no current PDPP surface and the mapping to it is speculative, so it fails the same test. One consequential follow-on: the deferred entry's closing line listed the four standards Section 1 relates to. It now lists three, because claiming a DPV row that no longer exists would send a reader looking for it. Verified: pnpm spec:check, pnpm spec:dates, and the spec prose gate against a merge-base baseline all pass, the last reporting no new findings. Writing the IEEE row as a single sentence tripped the gate's 25-word cap at 43 words, so it is two sentences. Assisted-by: AI Signed-off-by: Tim Nunamaker --- spec-core.md | 5 ++--- spec-deferred.md | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/spec-core.md b/spec-core.md index b3aaed339..8c035f0b2 100644 --- a/spec-core.md +++ b/spec-core.md @@ -51,9 +51,8 @@ Sections 4-8 define the protocol surfaces that implementations evaluate independ | [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 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) | IEEE 7012-2025 inverts the usual direction of an online agreement. The individual is the first party and proffers privacy terms chosen from a roster kept by a neutral non-business entity, and both sides keep a matching record. A PDPP grant records an authorization, not an agreement, and carries recipient commitments as structured fields rather than prose. A future version could let a grant reference an agreement identifier; v0.1 defines no such field. PDPP does not claim conformance. The standard expects both parties to hold a record and permits a counter-offer, where PDPP defines one record and issues it after consent. | -| [W3C DPV 2.3](https://w3id.org/dpv) | The Data Privacy Vocabulary supplies consent-record terms that PDPP's structured policy declarations correspond to. It keeps purpose, consent, and the consent record as distinct classes, as PDPP does. Its consent record references a notice object rather than a bare URL. That is why PDPP states plainly that a recorded URI identifies which document was shown, not what it said. DPV 2.3 carries a live extension for IEEE 7012-2025, `STANDARD-IEEE-7012`, which names the `Agreement` and `AgreementRegistry` concepts a future PDPP terms mapping would target. DPV is a Community Group report and is not a W3C standard. | -| [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. It is 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. It is not a v0.1 conformance requirement. | +| [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. | diff --git a/spec-deferred.md b/spec-deferred.md index ac5084f20..4565c2867 100644 --- a/spec-deferred.md +++ b/spec-deferred.md @@ -215,7 +215,7 @@ _Newly deferred (2026-09-03); written in response to the question of whether PDP **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, DPV, ISO/IEC TS 27560, and ISO/IEC 29184. +**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