Normalize Extensions v2 contract - #252
Conversation
There was a problem hiding this comment.
Review completed against the latest diff
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 16 files
Requires human review: Auto-approval blocked because this review re-detected 3 unresolved issues already reported by Cubic.
Re-trigger cubic
There was a problem hiding this comment.
1 issue found across 9 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/services/extensions/v2/db/developer-claims.ts">
<violation number="1" location="src/services/extensions/v2/db/developer-claims.ts:312">
P3: The `scope=mine` cursor is bound only to scope, not to the claimant, even though `claimantId` is the primary filter of that result set. A cursor minted by one user, passed with another user's `scope=mine` request, decodes cleanly and seeks from the first claimant's key boundary, silently skipping the second claimant's newest claims — the same "wrong key boundary" page this PR rejects for scope and history. In contrast, the `listHistory` binding added in this same delta tags the developer id (`d`) and rejects a foreign one. Tag the claimant id for `scope=mine` and validate it on decode, mirroring `decoded.d` in `listHistory`.</violation>
</file>
There was a problem hiding this comment.
All reported issues were addressed across 6 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
There was a problem hiding this comment.
0 issues found across 1 file (changes from recent commits).
Requires human review: This PR introduces a breaking public API contract change and coordinated site migration that requires human sign-off.
Re-trigger cubic
Breaking-within-v2 contract tidy. No D1 migration; coordinated release with the site PR (FOSSBilling/extensions#343, same branch name).
What changed
GET /developers,GET /developers/claims,GET /developers/{id}/historymove from offset to keyset cursors (PaginationSchema); offset helpers deleted. Same-second ties still broken by rowid.GET /developers?scope=all|unapproved(?status=kept as deprecated alias, 422 on explicit conflict);scope=pending+ disagreeingstatusnow 422 instead of silently ignored.POST /extensions/{id}/relist(+relist()DB,extension-relistedmail, revalidate).statusFromOwnershipErrorCodefolded intostatusFromWriteErrorCode; sharedNotifiedSchemafragment; tags by resource (listDevelopers, claim decisions →Developers).contract.test.ts(static-beats-param, reserved ids, scope-misuse matrix, cursor envelopes).[auto]note convention).Follow-up (deferred, builds on this): #251 moderator content-correction.
Testing
npm run typecheck,lint(0 errors),format:checkclean.test/services/extensions/v2/: 11 files / 321 tests pass, incl. new relist, scope/cursor, and contract coverage.No config/binding changes.