Skip to content

fix(diff): make POST /diffs functional with repo-addressed IRIs#270

Open
blake-regalia wants to merge 2 commits into
fix/review-findingsfrom
fix/diff-create
Open

fix(diff): make POST /diffs functional with repo-addressed IRIs#270
blake-regalia wants to merge 2 commits into
fix/review-findingsfrom
fix/diff-create

Conversation

@blake-regalia

Copy link
Copy Markdown
Contributor

Problem

POST /orgs/{org}/repos/{repo}/diffs has never worked. Compounding defects: the route never set diffId (every mord: reference resolved to the never-URN), the body was filtered against the lock prefix, the base conditions required a commit in the request path (404 on every request), genDiffUpdate ignored both its diffTriples and conditions parameters (user metadata dropped; no permit/uniqueness/ref validation at update time; mms:appliedPolicy never written, making the validation construct unmatchable so even successful writes returned errors), and cleanup deleted mt: while the transaction was created as mt:diff. There were zero diff tests.

Separately, the internal commit pipeline's empty-delta path (an idempotent client re-submitting the same update) permanently accreted a dangling mms:Diff referencing a never-created commit plus an orphaned AutoDiffOwner policy, on every no-op update.

Fix

  • c97ee0e — diffs are minted at repo-addressed IRIs {repo}/diffs/{id} (Slug header or generated), consistent with every other resource; the commit-pair sha256 is retained as mms:id and etag. The internal pipeline keeps its hash-derived IRIs. genDiffUpdate now actually embeds its conditions and user metadata. Responds 201 + Location.
  • e393c26 — the empty-delta path deletes the diff metadata and the transaction's created policy before responding.

Tests

New DiffCreateTest (5 tests): diff between a lock and a branch including ins-graph content verification, extra user metadata, generated ids, transaction cleanup, and the no-op-update leak invariant (no mms:Diff may reference a nonexistent commit). Full suite green (399/399).

Dependencies

Stacked on the review-findings branch (this PR's base): diff creation with user metadata requires the serializePairs separator fix from that branch. Retarget to develop after it merges.

Out of scope (needs design)

/diff/{diffId}/query remains non-functional: it resolves refs via mms:commit, which diffs don't carry, and the intended query semantics (ins/del graph union? named graphs?) are undefined. Left untouched pending a decision.

🤖 Generated with Claude Code

blake-regalia and others added 2 commits July 22, 2026 17:18
Diff creation was broken end-to-end by several compounding defects:

- the route never set diffId, so every reference to the diff resolved to
  the never-URN placeholder
- the request body was filtered against the lock prefix ("morl") instead
  of the diff prefix
- the base conditions required a commit in the request path (there is
  none on the diffs container), failing every request with 404
- genDiffUpdate ignored its diffTriples and conditions parameters
  entirely: user-supplied metadata was silently dropped, no conditions
  (permit, ref validation, uniqueness) were enforced at update time, and
  ?__mms_policy stayed unbound so the transaction lacked
  mms:appliedPolicy — which made the validation construct unmatchable
  and every request fail even after a successful write
- cleanup deleted mt: while the transaction was created as mt:diff,
  leaking a transaction record per request

Diffs are now minted at {repo}/diffs/{id} (Slug header or generated),
consistent with every other resource; the commit-pair scheme's sha256 is
retained as the mms:id and etag. The internal commit pipeline continues
to mint its own hash-derived IRIs. Responds 201 with a Location header.

Adds end-to-end tests: diff between a lock and a branch (including ins
graph content), extra user metadata (exercising serializePairs),
generated ids, and transaction cleanup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
genDiffUpdate unconditionally inserts the mms:Diff metadata and an
AutoDiffOwner policy before the delta is known (its WHERE ends in a
guaranteed-solution union), but the empty-delta path of
diffAndFinalizeCommit returns before the commit is created — so every
no-op update (e.g. an idempotent client re-submitting the same change)
permanently accreted a dangling mms:Diff referencing a commit that does
not exist, plus an orphaned policy.

Delete the diff metadata and the transaction's created policy in the
empty-delta path before responding.

Adds a test asserting that after a no-op update, no mms:Diff references
a nonexistent commit.

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

Copy link
Copy Markdown

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