Files
qbit-collaboration/docs/ATTACHMENT-PAGINATION.md
James MaesandClaude Sonnet 5.5 89e77b67b9 feat(attachments): reconcile reviewed attachment lifecycle, upload journal and retention SPI
Selective three-way reconciliation onto develop 7d61f29 (base c4eb972 = original
ancestor; theirs = reviewed b6fb2382 third-party-src/qbit-collaboration).
Attachments package (main and tests), upload journal (H2/MySQL/PostgreSQL),
cleanup queue, recovery/adoption processes, attachment schema fields, tables,
pagination, delivery schema, help text and docs. Upstream presence work, CI
workflows and release convention are untouched. Redis presence, my-work bounds,
notifier and custom-field changes in b6 are deliberately not included.

Targets qqq 4.1.0-RC.21 BOM. Needs core QBackendTransaction after-rollback
callbacks (not in RC.21): see docs/CORE-DEPENDENCY.md. Not compiled against RC.21.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-05 17:19:46 -06:00

3.0 KiB
Raw Permalink Blame History

Standard attachment list pagination

The standard GET /records/{table}/{pk}/attachments endpoint now applies its page offset and limit inside the native QQQ attachment query. It reads at most limit + 1 rows (maximum 101), projects the requested page, and uses the extra authorized row only to determine whether to emit the next cursor. It performs no count query and does not load the complete attachment list before slicing it.

The route, response schema, default limit 20, allowed limits 1–100, and existing version-1 scoped offset cursor bytes are unchanged. Sorting is still descending createDate, then descending id; equal timestamps therefore retain a stable tie order. These are offset pages, not snapshots: concurrent insertion or deletion can shift offsets. High offsets can require backend scanning; bounded returned rows and host allocation are not a constant-time database performance guarantee.

Each request still touches the current person, resolves and authorizes the actual source record, canonicalizes its primary key, excludes deleted-parent attachments, and uses the existing per-entry edit/delete policy. The same entry projection is evaluated for the lookahead row. There is no generic post-filter refill or inference from a denied row. Sources transferred to retained archive records use the exact current parent identity and its native authorization policy. This owner artifact does not import Record Files or reconstruct its archive policy.

Metadata visibility is separate from content release. Listing retained or quarantined metadata does not issue a download, preview or print capability; those paths retain their lifecycle and current authorization checks. The cursor is a routing/offset hint, not a signed authorization token. Current source access is required even when the caller presents a previously valid cursor.

AttachmentsService.listPage is the bounded public service operation. The older unpaged list method remains for compatibility; new page consumers should use listPage. Cursor parsing/encoding is shared with the existing complete-list pagination helper, so other Collaboration endpoints keep their previous behavior.

Verification: local focused run target/attachment-pagination-focused.log passed 40 tests on 2026-10-31 at 02:01:44, with zero failures/errors/skips and Checkstyle. Two new tests execute the actual QQQ RDBMS action against H2 and observe native offset/limit and returned-row bounds, equal timestamp ordering, deleted/other source exclusion, retained flags, terminal pages and current revocation before attachment SQL. The other 38 tests cover existing attachment service behavior and the unchanged OpenAPI fixture. Root HTTP run47446 also passed all12 tests, including the new regression covering three pages, cursor scope, malformed/oversized input and a denied actor. Cross-qbit archive integration, full release verification and installation of this new owner snapshot remain separate gates. No installed or frozen consumer artifact has been replaced by this change.