Skip to content

[10/10] docs(spec): stamp Date headers for this stack's changes - #299

Closed
tnunamak wants to merge 12 commits into
spec/int0902-09-normative-surface-reductionfrom
spec/int0902-10-date-stamps
Closed

[10/10] docs(spec): stamp Date headers for this stack's changes#299
tnunamak wants to merge 12 commits into
spec/int0902-09-normative-surface-reductionfrom
spec/int0902-10-date-stamps

Conversation

@tnunamak

@tnunamak tnunamak commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Housekeeping, not a decision. One row of the stack under #285.

Four files stamped 2026-09-02 across two commits: spec-core.md and spec-deferred.md, and — after the surface-reduction sub-PR edited them — spec-collection-profile.md and spec-discovery-and-trust.md.

spec-reference-implementation-examples.md is deliberately left unstamped and is the stack's one spec:dates failure. It fails identically on origin/main untouched — verified by running the checker in a clean worktree at origin/main, which reports exactly that file and nothing else. Stamping it would claim a substantive change this work did not make. Art's #283 makes the same call for the same reason.

spec-collection-profile.md was in that same pre-existing category until this stack edited it, and is stamped now because that is no longer true.

Assisted-by: AI

…ent shape

spec-core.md told a resource server to return stream metadata "whole
rather than field-projected by the grant" for GET /v1/streams/{stream}.
That sentence was written for an owner reading their own data, where
there's no grant to project against, but it applied unqualified to a
client-token request too. A resource server built strictly from that
prose would hand an approved app every current field, query capability,
view, and relationship a data source declares -- not just the ones the
user actually consented to. The reference implementation already does
the opposite for client tokens: it returns a closed projection scoped to
the frozen grant. An independent post-merge review of PR #243 (see
local/pdpp-pr243-retroactive-independent-review-2026-08-29.md) flagged
this as the one P1 left after that PR's owner-filter fixes landed.

This is a fix-forward on that review, not a rollback:

- spec-core.md: split "Get stream metadata" into owner (full current
  metadata, unchanged) and client (closed grant projection: granted
  fields only, no current query/view/relationship/expansion/aggregation
  capability, and a post-grant declaration addition never becomes
  visible) response shapes, with two separate example bodies. Extended
  RS conformance (Section 9, items 14-15) and the plain-English
  grant-enforcement algorithm / trust-boundary table (Section 8/10) to
  branch on pdpp_token_kind instead of reading as if every request needs
  a grant. Split the GET /v1/streams "under the current grant" sentence
  the same way.
- reference-implementation/test/spec-metadata-projection-consistency.test.ts:
  pins the three RI fixture facts the review named against a live
  server -- owner gets full capabilities, client gets only frozen grant
  fields, a field added after grant issuance stays invisible to that
  grant.
- .github/workflows/spec-check.yml: wires the existing but previously
  CI-unused `pnpm spec:owner-filter-check` scanner into the spec-check
  job, per the review's own follow-up ask.
- spec-data-query-api.md / its site header: relabels the
  self-contradictory "(original)" date tail to "(last corrected)" --
  the file can't have originated four months after it was superseded.

Verified: pnpm spec:check, spec:dates, and spec:owner-filter-check all
pass; the new test file and the existing
reference-implementation/test/query-contract.test.ts (61 tests) pass
unmodified against the reference implementation; tsc --noEmit clean.

Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
OWNER-DECISION: normative. Not ratified.

Source: owner alignment 2026-09-02 17:05 (OWNER-COMMITMENTS.md rows 68-69);
research in local/CIMD-STANDARDS-ANSWER-0902.md and
ai/research/protocols/oauth-client-id-metadata-documents-vs-gnap-client-identity-2026-09-02.md.

Row 68 recorded the gap: spec-core.md never addresses client ID metadata
documents (CIMD), the mechanism deployed MCP clients such as ChatGPT
actually use. Core knew only RFC 7591 vocabulary and "dynamic
self-registration when registration_endpoint is advertised". Three things
were undefined: where CIMD-derived name and logo rank in the client_display
precedence, whether a fetched https document counts as the "domain
verification" obligation 4 names only as an example, and who owes the fetch
and validation obligations.

Row 69 set the shape of the answer: the OAuth binding is where dynamic
registration and CIMD are required, so Core stays binding-neutral and adds
only what a binding-neutral core can state.

Three changes:

1. Section 1's standards table gains a CIMD row, recording that MCP
   2025-11-25 ranks CIMD SHOULD and RFC 7591 DCR MAY (backward
   compatibility), and that the fetch/validation obligations sit in the
   binding, not in Core.

2. Section 6 defines "validated binding metadata" and inserts it into the
   requester-identity precedence between validated software statements and
   inline client_display. The rationale is stated in the text: the AS
   checked it; the client did not merely assert it.

3. Obligation 4's parenthetical becomes "verified domain control", and a new
   obligation 5 defines what verified domain control is and constrains how
   it may be presented: name the domain, never claim an unqualified
   "verified app", and never imply review of the client's conduct. This
   matches the trust-model decision at OWNER-COMMITMENTS.md row 64.

RFC 7591 field names are kept verbatim inside client_display, per row 69.
Obligations 5 and 6 renumber to 6 and 7; no other text changed.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…open

OWNER-DECISION: normative only in that it changes what v0.1 claims to have
decided. Not ratified.

Sources:
- Geneva notes (d), Anna, relayed 2026-09-02:
  https://vana-org.slack.com/archives/C0B9AKY6ZDH/p1788337128917169
  "derivative data should be in scope. PDPP doesn't have an answer for
  derivative data."
- Geneva notes (e), Art, same message: users will want to grant by category
  across sources ("my health data", not five named providers), similar to
  PDPP's views within a source. Standards to look at were cited but not
  named in the message; the candidate list is recorded as unevaluated.
- Art, 2026-09-02:
  https://vana-org.slack.com/archives/C0B9AKY6ZDH/p1788351571550459
  ToIP's Trust Registry Query Protocol; expose the register as a TRQP
  endpoint from phase 2, DTI recognition becomes a TRQP query. Explicitly
  "a design commitment, not a date" — it is in public review with no test
  suite.

Three entries added to spec-deferred.md's open design questions, and two
rows added to Core's Section 12 out-of-scope table so the first two are
findable from Core.

Anna's observation that (d) and (e) are related is not folded into one
entry. Granting "my health data" across providers is a vocabulary and
scope-widening problem; whether an embedding of those records needs its own
grant is an authorization-object problem. They meet in the case where a
category is defined by derivation rather than by source, and each entry
names the other's neighbourhood, but merging them would hide two questions
inside one.

The derivative-data entry states that v0.1's silence is not permission.
That is the sentence to argue with if any of this is wrong: it is the only
place these three entries make a claim rather than record a question.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…gateway

OWNER-DECISION: normative (adds one SHOULD NOT). Not ratified.

Sources: Geneva notes (c) and (f), relayed 2026-09-02:
https://vana-org.slack.com/archives/C0B9AKY6ZDH/p1788337128917169
and the owner's clarification in-thread:
https://vana-org.slack.com/archives/C0B9AKY6ZDH/p1788342568209169
"the spec could refer to authorization and resource servers without
defining how data gets into the resource server ... The Collection Profile
spec can define how data connectors can get data into a resource server."
Note (f) asked for a sanity check on a personal server acting as a gateway
to platform data using an owner credential against the platform's PDPP API.

Two additions to Section 3, after Example B.

First, Core states plainly that it defines no ingest path and that
conformance does not depend on one. Section 3 already called its two
examples a spectrum rather than a closed set; this says the same thing as a
statement about Core's scope rather than as a caveat about the examples.

Second, the gateway idea is recorded as already permitted, because it is:
the personal server is a conformant client in the first relationship and a
conformant resource server in the second. Nothing new is needed to build
it. The open part is not whether it works but what the onward grant may
say about the originating one, so the paragraph names that question and
adds an interim SHOULD NOT against issuing an onward grant broader or
longer than the grant the records arrived under.

WHAT THIS DOES NOT DO, and why:

The instinct in note (c) was that connectors and native mode "are currently
superficial and can be edited out of the core spec entirely". They are not
superficial, and this branch does not remove them. `source.kind` is a
required field of the source declaration, its two values are validated
against the accepted declaration before consent, a mismatch is a Source
validation failure, and the derived provenance is recorded in consent
evidence and in the issued grant. Art's open #283 adds a further normative
rule keyed on `provider_native`. Removing `source.kind` is a breaking change
to the declaration schema and the grant, not an editorial deletion, and it
would conflict with #283 rather than compose with it.

What note (c) actually asked for -- that Core not define how data reaches
the resource server -- is what this commit states, and what #283 delivers
from the other direction by making the Collection Profile informative.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…ated one

OWNER-DECISION: normative. Not ratified. Revises the gateway paragraph
added earlier on this branch (8e0d96a) rather than adding a second one.

Source: owner scope addendum 2026-09-02 ~17:40, item C: follow precedent,
invent nothing.

The earlier commit already said the gateway works and needs no new
protocol element. What it did not do was name the precedent or state the
negative, and it left the UMA-style topology unaddressed rather than
deferred. Three changes:

1. States the negative explicitly: PDPP defines no delegated-grant,
   sub-grant, or grant-chaining construct, and none is needed. The chain is
   two independent grants, each issued by the owner, each revocable on its
   own. A reader who arrives looking for a delegation primitive now finds
   the answer instead of an absence.

2. Names the precedent rather than reasoning from first principles: open
   banking aggregators already work this way -- consent at each bank plus
   consent from the user, not one authorization subdivided. RFC 8693 OAuth
   Token Exchange is named as the binding-level mechanism where a
   credential must cross the two relationships, and is explicitly placed in
   the binding rather than in Core, consistent with how this branch handles
   CIMD.

   Plaid is deliberately NOT named. It is the same pattern as the open
   banking aggregator already cited, and naming a single commercial vendor
   in a normative specification invites both a fairness objection and a
   staleness problem. The pattern is what carries the argument.

3. Records the UMA-style topology -- owner runs their own authorization
   server in front of a platform's data -- as NOT introduced here, and
   points at spec-deferred.md rather than leaving a reader to wonder
   whether it was overlooked or excluded. The deferred entry itself is a
   separate commit.

The interim SHOULD NOT on onward grant scope and duration is unchanged
from the earlier commit; only its surrounding context moved.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…itions

OWNER-DECISION: normative. The sector-regimes paragraph states that the
stricter regime governs, which is a requirement, not a description. Not
ratified.

Source: Art, 2026-08-25, before the GDC handouts printed:
https://vana-org.slack.com/archives/C0B9AKY6ZDH/p1787815124927929

He asked for two positions to be printable, and asked where the spec says
them. Both asks were "is this accurate to the spec, and where do we say
it?" -- and for both, the answer was that the spec did not say it.

1. UMA/GNAP. His proposed position, printed here close to his own wording:
   PDPP is a data-portability profile, not a general authorization
   framework; it rides OAuth + RAR because that is what is deployed; it
   adds what neither UMA nor GNAP defines; a GNAP binding is possible
   later. The standards table already carried the raw material in the UMA
   and GNAP rows, but as two entries a reader had to assemble. This states
   the conclusion, and adds the reason a later GNAP binding stays possible:
   the record model, the grant, and the resource server interface do not
   depend on the protocol that produced the grant.

2. Sector regimes. Floor, not ceiling. His ask was to confirm the connector
   model supports the claim as stated. It does, but the specification never
   said so, and "recognized, plug in via connectors, keep every guarantee"
   is not derivable from silence. The paragraph states that the stricter
   requirement governs, that PDPP authorizes no disclosure the source's own
   regime forbids, and that a PDPP grant does not substitute for a consent
   that regime requires.

Art also asked that (2) be filed as one of the first public review issues,
"Recognition of sector-specific consent regimes", so the position lands
with a paper trail. That is an issue to open, not a spec edit, and this
branch does not open it.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
OWNER-DECISION: not normative. Three open questions recorded, no
requirement added or changed. Not ratified.

Source: PDPP working session on grants, 2026-08-19, recapped in
#vana-org by Kat:
https://vana-org.slack.com/archives/C0B9AKY6ZDH/p1787246400660469
and in the session summary:
https://vana-org.slack.com/archives/C0B9AKY6ZDH/p1787249010667589

The recap listed six questions and named the owner as the next step on
several. Grepping the specification set for each: subgrants, change of
client ownership, undisclosed sub-processing, ISO MyTerms and bulk export
appear nowhere in any spec-*.md file. They existed only in Slack and in
the session recording. Three entries are added so they are referenceable
from Core and survive the next person who looks.

The other two questions in that recap already have homes and are not
duplicated here: cursor-based sync prior art (WebDAV report/sync token and
the rest) is a design input rather than an open question, and the adoption
argument is not a specification concern.

Subgrants and change-of-ownership are stated as questions with a v0.1
posture, not as answers. The bulk export entry records that half of it is
already decided -- owner self-export is a SHOULD-level RS conformance item
in Core Section 9 -- so the open part is only the client-under-grant case.

The change-of-ownership entry says `client_claims` is not an ownership
record and must not be read as one. That is a reading of the existing
trust-boundary text, which already says client claims are self-asserted,
unverifiable, and outside the resolved grant. If it reads as a new
restriction rather than a restatement, it should be cut.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…'s own server

OWNER-DECISION: normative. Adds a MUST NOT. Not ratified.

Source: owner framing relayed 2026-09-02 ~18:10, covering Linear DEL-239
(https://linear.app/vana-team/issue/DEL-239/decide-whether-a-grant-recipient-can-pass-part-of-their-access-to)
and its distinction from the topology-B case.

Two rules, and the point is the line between them.

1. Onward transfer by a THIRD PARTY is forbidden by default. A client
   holding a grant MUST NOT transfer or re-delegate that access; a second
   party gets a grant from the owner or gets nothing. Stated with the
   precedent rather than as a bare assertion: an OAuth access token is not
   transferable, open banking authorizations are per recipient, and GNAP
   routes a new party back through the authorization server. It also
   follows from PDPP's own purpose limitation -- a grant records the
   purpose the owner approved for one named requester, so a transfer would
   carry access without the approval that scoped it.

2. The owner's own personal server is NOT that case. The copy it holds is
   the owner's data, and the app grant is issued fresh by the owner there.
   No delegation construct, because no access is passed along: the owner
   authorizes twice, in two places.

   In the passthrough posture only -- server does not retain a copy, reads
   from the platform to fulfill as requests arrive -- the owner's grant to
   their own server at the platform covers fulfillment for clients that
   owner authorizes at that server. Account aggregation is the precedent:
   the user's consent at the bank covers the services the user chose, and
   the bank never sees the downstream app.

No new construct is introduced by either rule. That is the substance of the
decision, not an aside: the alternative reading -- that fulfilling on the
owner's behalf requires a delegated or chained grant -- is what this text
exists to foreclose.

spec-deferred.md's Subgrants entry is rewritten to match. It previously
read as an open question with transfer merely "out of scope"; it now
records that transfer is forbidden today and that what remains open is
whether a future version defines a supervised relaxation. It also names the
two cases that are NOT subgrants, so a later design does not re-describe
them as delegation.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
OWNER-DECISION: not normative. Two deferred-register additions. Not
ratified.

Sources: owner scope addendum 2026-09-02 ~17:40, items C and E.

Item C's second half: the topology where the owner runs their own
authorization server in front of a platform's data is explicitly NOT
introduced. It is added as a named deferred entry rather than left
unmentioned, so a reader who knows UMA can tell the omission is a decision.
The entry states why it is hard -- it needs a platform's resource server to
honor grants from an authorization server the platform neither operates nor
chose -- and distinguishes it from the on-behalf-of chain now in Section 3,
which is a different shape and is permitted.

Item E: the existing TRQP entry on this branch already recorded the
mechanism, the "design commitment, not a date" framing, and phase 2. What
it did not say is where it would live. Added: in a profile or binding, not
in Core's normative text, with the reason -- naming a document still in
public review and without a test suite inside Core would bind the
specification to it. This matches how this branch places the CIMD fetch
rules and RFC 8693 in the binding rather than in Core.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
OWNER-DECISION: normative. Three new requirements in Core; two documents
demoted out of the normative set. Not ratified.

Source: owner scope addendum 2026-09-02 ~17:40, item B; text taken from the
sibling audit at local/SPEC-SURFACE-AUDIT-0902.md (inserts A, B and C of
its section 1.5). The audit is read-only analysis by a separate lane; this
commit applies its proposed text, it does not re-derive it.

Art wants v0.1.0's normative surface to be the core spec alone. The audit
traced what actually depends on the two companion documents and found the
load-bearing residue is about 200 words. Applied here:

1. Equivocation, into Section 5 Versioning and snapshots. Core already said
   declaration_version is opaque with no implied ordering; it never said
   what happens when the SAME version label later carries DIFFERENT content.
   That is the security property -- it is what stops a publisher swapping
   content under a label an authorization server already consented against
   -- and it was the single genuine gap. Now a MUST.

2. Source acceptance, as a new Section 6 subsection. Core described what a
   selection request contains, never what it may not name. The rule that a
   client cannot introduce a source authority, declaration location, or
   revision during authorization is enforced fail-closed in the reference
   implementation's PAR path today; Core now states it.

3. Publisher attribution, replacing two dangling pointers. Core deferred
   twice to "discovery and trust policy" -- a document that, after Art's
   #279 removes Official Source, has zero inbound references anywhere in
   the repository. The rule is now stated where the field is defined.

Both companion documents are relabelled Informative in their root status
lines, and both header sidecars gain the Informative callout they never
had, so the site stops rendering them beside Core with no visible status
distinction.

WHAT THIS DELIBERATELY DOES NOT DO:

The Collection Profile is NOT moved to data-connectors tonight, on the
audit's recommendation and for a reason worth repeating: a manifest written
to its published bindings table is rejected by the reference
implementation's own validator (the spec publishes `browser_automation`;
the validator accepts `browser` and hard-rejects unknown keys; 0 of 45
shipping manifests use the published name). Moving a known-wrong contract
into the repo whose authors are its primary readers ships the defect to
exactly the people most likely to follow it. Reclassify now, refresh, then
move something true.

The three extension profiles are left alone. They are already allowlisted
in ratified OpenSpec governance, CI-enforced, status-labelled, and required
not to be depended on by Core. They are the pattern, not the problem.

README.md and the site rail's grouping are NOT touched here, though both
are stale in exactly this respect. Art's open #283 makes those same edits.
Duplicating them guarantees a conflict and gains nothing. The slug list
keeps a comment explaining why it was left unrestructured.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Not an owner decision. spec:dates reported four stale files on this branch.
Two are caused by this branch (spec-core.md, spec-deferred.md) and are
stamped 2026-09-02.

The other two, spec-collection-profile.md and
spec-reference-implementation-examples.md, already fail on origin/main
untouched -- verified by running scripts/spec-date-check.ts in a clean
worktree at origin/main, which reports exactly those two and nothing else.
They are left alone, because stamping them would claim a substantive change
this branch did not make.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Not an owner decision. Both documents changed substantively on this branch
-- their status lines moved from normative-companion to informative -- so
both are stamped 2026-09-02.

spec-reference-implementation-examples.md remains unstamped and remains the
one spec:dates failure on this branch. It fails identically on origin/main
untouched; stamping it would claim a substantive change this branch did not
make. spec-collection-profile.md was in that same pre-existing category
until this branch edited it, and is stamped now because that is no longer
true.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
@vercel

vercel Bot commented Sep 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
pdpp Ready Ready Preview Sep 2, 2026 11:41pm UTC

Request Review

@tnunamak

tnunamak commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Closing: the date stamps this PR carried now travel with the changes that make them stale — spec-core in #290, spec-deferred in #293, and the two demoted companions in #298. That way each PR in the stack is individually green on root/site spec drift instead of every intermediate PR being red until the last one lands.

spec-reference-implementation-examples.md remains deliberately unstamped; it fails spec:dates identically on origin/main untouched, and stamping it would claim a substantive change this stack did not make.

@tnunamak
tnunamak force-pushed the spec/int0902-09-normative-surface-reduction branch from 2e5c0c0 to 155d545 Compare September 2, 2026 23:49
@tnunamak tnunamak closed this Sep 2, 2026
@tnunamak
tnunamak deleted the spec/int0902-10-date-stamps branch September 2, 2026 23:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant