Skip to content

spec: add an optional change feed (GET /changes) for index-time federation (#96) - #108

Open
kperry-godaddy wants to merge 1 commit into
ards-project:mainfrom
kperry-godaddy:spec/96-change-feed
Open

kperry-godaddy wants to merge 1 commit into
ards-project:mainfrom
kperry-godaddy:spec/96-change-feed

Conversation

@kperry-godaddy

Copy link
Copy Markdown

Normative text for the change feed proposed in #96. One optional endpoint, GET /changes: an ordered, cursor-driven, replayable feed of the identifiers a registry added, updated, or removed, and nothing else. A consumer fetches each entry from the identifier's authority (the <publisher> domain, resolved as §5.1 directs) and confirms every delete there. The feed says what exists and what changed; the authority says what the entry says.

What changes

  • spec/ard.md
    • New §5.5 Change Feed (GET /changes) — Optional: request, response, change object, cursor and delivery rules, the retention window, producer rules, consumer rules, security, errors. Placed after §5.4 so it does not renumber §5.3.x (PR Add direct catalog entry lookup by identifier #74 adds there).
    • §5 intro names the new layer; §5.2 gains a "Change-Feed Subscription (Optional)" pipeline bullet; §5.4 gains one paragraph naming query-time and index-time federation and stating that federation: none keeps its meaning.
    • Appendix B adds 410 CURSOR_EXPIRED and names 501 NOT_IMPLEMENTED (Explore already returns 501 without a code).
    • D.3 lists GET /changes among the OpenAPI-defined interfaces. D.4 is untouched: conformance tooling is a follow-up PR.
  • spec/schemas/ard.openapi.yaml: /changes path (cursor, limit; 200/400/401/410/429/501/500), a ChangeFeedResponse schema referencing the new JSON Schema the same way SearchResultItem references ard-entry.schema.json, and a 410CursorExpired response. info.version left for the publishing commit.
  • spec/schemas/ard-change.schema.json (new): Cursor, Change, ChangeFeedResponse. Validated against the 2020-12 metaschema and against the §5.5.2 example plus negative cases.
  • spec/schemas/ard.cddl: cursor, change, changes-response.
  • adr/0011-index-time-federation-change-feed.md (new): context, decision, why identifiers rather than entries, alternatives, exclusions, consequences. Numbered after the merged ADR-0010; renumber if Add direct catalog entry lookup by identifier #74 lands first.

Decisions taken on the open questions in #96

Question What this PR does
Q1 identifiers only Yes. A change is {cursor, op, time, identifier}; the change object is closed (additionalProperties: false).
Q2 optional vs required Optional with 501, as for Explore; a registry operated as an upstream for other registries SHOULD implement it. One sentence; easy to drop if the group prefers plain optional.
Q3 retention Sliding window that MUST contain every held identifier, met either by indefinite retention (never 410, retention omitted) or by re-emitting an identifier's latest change before it ages out. Floor: SHOULD P7D. Cursor older than the window → 410 CURSOR_EXPIRED → staged replay; the live index is never emptied.
Q4 unreachable authority A delete is never applied while the authority cannot be reached; how long an entry then survives is the same question §5.2 leaves open for crawled entries, and the text says so rather than inventing a lifetime here.

Deliberately not in this PR

Checks

  • OpenAPI parses; every $ref (internal and to both JSON Schema files) resolves.
  • JSON Schema passes the Draft 2020-12 metaschema; the §5.5.2 example validates; unknown op, extra properties, bad cursors, bad durations, and >1000 changes are rejected.
  • Conformance demo still passes (it does not read the changed files; included as a smoke test).

Closes nothing on its own; tracks #96. Related: #63, #87, #88, #94, PR #74.

🤖 Generated with Claude Code

…ation (ards-project#96)

New §5.5 defines an ordered, cursor-driven, replayable feed of the
identifiers a registry added, updated, or removed. The feed carries no
entry content: a consumer fetches each entry from the identifier's
publisher domain (§5.1) and confirms every delete there, so the trust
rules are unchanged from crawling and mutually subscribed registries
converge without a hop list. Cursors are opaque; delivery is
at-least-once, latest change per identifier; the retention window must
contain every held identifier, so a new consumer replays it once with no
snapshot endpoint and no 410 mid-replay. Optional, 501 like Explore.

Also: the §5 intro names the new layer; §5.2 gains a change-feed
subscription pipeline bullet; §5.4 gains a paragraph naming query-time
and index-time federation; Appendix B gains 410 CURSOR_EXPIRED and names
501 NOT_IMPLEMENTED; D.3 lists the endpoint. The OpenAPI definition
gains /changes and a 410 response; ard-change.schema.json defines the
page and change objects and ard.cddl restates them. ADR-0011 records the
decision, the alternatives, and what was deliberately left out.

Identifier forms whose authority is not a publisher domain, and the
conformance tooling for producers and consumers, are left to follow-up
PRs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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