docs(contract): mark scan cursor v1-provisional (offset, not snapshot); route conformance gap to bifrost-dev

Operator accepted offset-cursor for v1 (person-prime single-page is
conformant). INV-010 now documents the KNOWN DEVIATION: multi-page
continuation diverges from bifrost's protocol snapshot-cursor contract
(dispatch drops sort on continuation, ScanCursorExpired normative) — our
offset cursor doesn't snapshot (dup/drop under concurrent write) and never
expires. Durable fix routed to bifrost-dev as a conformance-coverage gap
(scan/cursor is untested); ratatoskr will adopt reference snapshot-cursors
if bifrost rules them normative.
This commit is contained in:
2026-07-15 08:52:29 -07:00
parent 66ba06875e
commit 8199774405
2 changed files with 15 additions and 1 deletions
@@ -145,6 +145,20 @@ interpreted.
`updated_at desc`), matching bifrost's cross-pagination conformance negative. The sort
field is indexed (`json_extract(record_json, '$.updated_at')`) so the read stays within
person-prime's 500 ms fail-open budget.
- **Cursor is v1-provisional (KNOWN DEVIATION — offset, not snapshot).** The cursor is a
bare integer offset into the re-derived global order. This is CORRECT and conformant for
the **single-page** person-prime call (`cursor=None`), which is the only shipped consumer.
It **diverges from bifrost's protocol snapshot-cursor contract on multi-page continuation**:
the dispatch engine (`bifrost.memory` scan branch) drops the `sort` arg on a cursor
continuation because "the cursor's snapshotted order is authoritative", and maps
`ScanCursorExpired → 410`. Our offset cursor (a) does NOT snapshot the order — a page taken
after a concurrent write can duplicate/drop rows relative to the first page (heid-bug-hunt
2026-07-15, all 3 arms), and (b) never raises `ScanCursorExpired`. The `global_before_paginate`
/ cursor test asserts **static-store** behavior only. The durable/conformant fix is to adopt
the reference `InMemoryMemoryStore`'s snapshot-cursor semantics (opaque token + frozen ordered
id-list + TTL + `ScanCursorExpired`); DEFERRED pending bifrost-dev's ruling on the conformance
gap (scan/cursor has NO conformance coverage today, so a non-snapshot cursor passes). Routed
to bifrost-dev 2026-07-15.
## Concurrency