Skip to content

Spec conformance: pagination, commit changes, previousCommit, Error shape, select projection, /meta datatypes - #29

Open
blake-regalia wants to merge 7 commits into
fix/review-findingsfrom
feat/spec-conformance
Open

Spec conformance: pagination, commit changes, previousCommit, Error shape, select projection, /meta datatypes#29
blake-regalia wants to merge 7 commits into
fix/review-findingsfrom
feat/spec-conformance

Conversation

@blake-regalia

Copy link
Copy Markdown
Contributor

Important

Stacked on #28 — merge that first. This branch builds directly on fix/review-findings (its pagination, error-shape, and test scaffolding depend on those fixes), so the PR is based on that branch to keep the diff reviewable: only the seven Phase-3 commits appear here. When #28 merges, GitHub will retarget this PR's base to develop automatically.

Summary

Seven increments closing the highest-impact conformance gaps between this service and the OMG Systems Modeling API spec. The suite grows from 55 to 74 tests, all green against the layer1 + Fuseki test stack.

  • Cursor paginationpage[size]/page[after] (the spec's parameter names, previously bound as pageSize/pageAfter and ignored everywhere) now work on every list endpoint, with a Link: rel="next" header advertising continuation:
    • GET .../elements pages at the SPARQL level (ordered by element IRI with a cursor filter, fetching one extra row to detect continuation) instead of always streaming the whole model graph — the endpoint no longer OOMs/times out on large models.
    • projects, branches, tags, commits, queries, and roots page through a shared respondPage helper. Requests without paging parameters keep their historical unpaged responses, including the commits list's newest-first ordering.
  • Commit changes endpoints (previously 501) — GET .../commits/{id}/changes and .../changes/{changeId} compute a commit's changes by diffing its model graph against its parent's (layer1 stores the raw SPARQL patch, which cannot be mapped back to per-element DataVersions). Created/modified elements carry their payload at the commit; deleted elements carry a null payload (DataVersion.payload is now nullable per the spec). Change ids derive deterministically from commit + element ids so single changes are stably addressable.
  • Commit.previousCommit (previously hardcoded null) — resolved from mms:parent so clients can reconstruct commit history. Flexo's auto-created root commit, which this API hides from the commit list, is never referenced (and is no longer addressable by id); the single-commit GET reads the commit collection since layer1's single-commit response lacks the parent's triples.
  • Spec-shaped Error responses — StatusPages returns the spec's Error object instead of plain text; 500s log the cause server-side and return a generic description instead of echoing internal exception messages (IRIs, paths) to clients.
  • Query select projection — stored/submitted select was echoed back but ignored at execution; both query-results routes now project each result object to the requested properties.
  • Real /meta/datatypes (previously a hardcoded openapi-generator example payload) — serves the 389 schema definitions from the bundled official OMG spec (resources/openapi.json, added to the main resource set): the collection as a $defs map per the spec's response shape, single datatypes by name, 404 for unknown ids.

Deliberately out of scope

ETag/If-Match on success responses, projectUsage/excludeUsed semantics (needs a design decision on used-project federation), and diff/merge remain open — tracked for follow-up work.

Test plan

  • docker compose -f src/test/resources/docker-compose.yml up -d
  • ./gradlew test — 74 tests, 0 failures (new suites: PreviousCommitTest, ErrorShapeTest, ElementPaginationTest, CollectionPaginationTest, ChangesTest, MetaTest, plus projection cases in QueryResultsTest)

🤖 Generated with Claude Code

blake-regalia and others added 7 commits July 18, 2026 17:05
previousCommit was hardcoded null (implementation commented out), so
clients could not reconstruct commit history. It now links to the
parent commit, except when the parent is flexo's auto-created root
commit, which this API hides — linking to it would dangle. The
single-commit GET fetches the commit collection since layer1's
single-commit response lacks the parent's triples; the hidden root is
also no longer addressable by id.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
StatusPages returned plain-text bodies, which official clients cannot
parse, and the catch-all echoed raw exception messages (internal IRIs
and paths) to clients. Failures now carry the spec's Error object; 500s
log the cause server-side and return a generic description.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Query.select was stored and echoed back but ignored at execution —
results always contained full elements. Both query-results routes now
project each result object to the requested properties.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
page[size]/page[after] (the spec's parameter names, previously bound as
pageSize/pageAfter and ignored) now page the element collection at the
SPARQL level — ordered by element IRI with a cursor filter and one
extra row to detect continuation — instead of always streaming the
whole model graph. A Link rel="next" header advertises the next page.
Unpaged requests keep the historical full-dump behavior. Replaces the
dead listElementsConstructQuery.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
projects, branches, tags, commits, queries, and roots now honor
page[size]/page[after] through a shared respondPage helper (ordered by
id, Link rel="next" when more remain). Requests without paging params
keep their historical unpaged responses, including the commits list's
newest-first ordering.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A commit's changes are computed by diffing its model graph against its
parent's — layer1 stores the raw SPARQL patch, which cannot be mapped
back to per-element DataVersions. Created/modified elements carry
their payload at the commit; deleted elements carry a null payload
(DataVersion.payload is now nullable to allow this, matching the spec).
Change ids are derived deterministically from commit and element ids so
GET .../changes/{changeId} is stable. Both endpoints paginate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both meta endpoints returned a hardcoded openapi-generator example
payload — syntactically valid JSON that meant nothing. They now serve
the 389 schema definitions from the bundled official OMG spec
(resources/openapi.json, added to the main resource set): the
collection as a $defs map per the spec's response shape, single
datatypes by name with a 404 for unknown ids.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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