chore(assets): drop cross-repo prose from cursor comments

Strip prose references to sibling Go implementations and external
ticket IDs from cursor.py, the cursor tests, the keyset integration
tests, asset_management's sort-field comment, and the legacy
prompt_id alias comment. Pure docstring/comment scrub — no behavior
or wire-format changes. x-runtime: [cloud] field annotations in
openapi.yaml are unchanged; those are the spec's structural
cross-runtime convention, not internal references.
This commit is contained in:
Matt Miller 2026-05-20 21:35:26 -07:00
parent 9a7f580b37
commit ab47c85f95
5 changed files with 23 additions and 34 deletions

View File

@ -173,7 +173,7 @@ def _build_asset_response(result: schemas.AssetDetailResult | schemas.UploadResu
user_metadata=result.ref.user_metadata or {}, user_metadata=result.ref.user_metadata or {},
metadata=result.ref.system_metadata, metadata=result.ref.system_metadata,
job_id=result.ref.job_id, job_id=result.ref.job_id,
prompt_id=result.ref.job_id, # deprecated: mirrors job_id for cloud compat prompt_id=result.ref.job_id, # deprecated alias of job_id, kept for compatibility
created_at=result.ref.created_at, created_at=result.ref.created_at,
updated_at=result.ref.updated_at, updated_at=result.ref.updated_at,
last_access_time=result.ref.last_access_time, last_access_time=result.ref.last_access_time,

View File

@ -253,9 +253,8 @@ def get_asset_by_hash(asset_hash: str) -> AssetData | None:
return extract_asset_data(asset) return extract_asset_data(asset)
# Sort fields that support cursor pagination. Mirrors cloud's allowlist # Sort fields that support cursor pagination. `last_access_time` is not
# (created_at, updated_at, name, size). `last_access_time` is OSS-only and # in this list — it falls back to offset/limit.
# falls back to offset/limit — no cloud contract to match.
_CURSOR_SORT_FIELDS = ("created_at", "updated_at", "name", "size") _CURSOR_SORT_FIELDS = ("created_at", "updated_at", "name", "size")

View File

@ -1,8 +1,6 @@
"""Opaque keyset-pagination cursor for /api/assets. """Opaque keyset-pagination cursor for /api/assets.
Wire format aligns with the cloud Go implementation in Payload JSON uses short keys to keep the encoded length small:
`common/pagination/cursor.go` so the frontend sees one contract across
runtimes. Payload JSON uses short keys to keep the encoded length small:
{"s": <sort_field>, "v": <value>, "id": <id>, "o": <order>} {"s": <sort_field>, "v": <value>, "id": <id>, "o": <order>}
@ -10,14 +8,12 @@ The `o` key binds the cursor to the sort direction it was minted under,
so replaying a `desc` cursor against an `asc` request fails with so replaying a `desc` cursor against an `asc` request fails with
``INVALID_CURSOR`` rather than silently walking the wrong direction. ``INVALID_CURSOR`` rather than silently walking the wrong direction.
`o` is mandatory on every payload a cursor without it is rejected as `o` is mandatory on every payload a cursor without it is rejected as
malformed. Cloud will land the same field in its mirror PR; until then, malformed.
Python and cloud cursors differ by exactly the `o` key, and a cloud-
minted cursor cannot be decoded by this endpoint.
Encoding is base64url with no padding. JSON serialization escapes `<`, Encoding is base64url with no padding. JSON serialization escapes `<`,
`>`, `&`, U+2028, and U+2029 to match Go's default `json.Marshal` `>`, `&`, U+2028, and U+2029 to match Go's default `json.Marshal`
behavior so asset names containing those characters produce behavior so asset names containing those characters produce
byte-identical cursors across runtimes. byte-identical cursors across compatible Go implementations.
Time values are serialized as Unix microseconds (UTC) microsecond Time values are serialized as Unix microseconds (UTC) microsecond
precision matches PostgreSQL's `timestamp` type, so a cursor minted from precision matches PostgreSQL's `timestamp` type, so a cursor minted from
@ -44,12 +40,9 @@ class InvalidCursorError(ValueError):
# decode path from oversized allocations and downstream SQL predicates from # decode path from oversized allocations and downstream SQL predicates from
# unbounded strings. # unbounded strings.
# #
# MAX_CURSOR_VALUE_LENGTH is 512 (vs cloud's 256) to fit OSS's # MAX_CURSOR_VALUE_LENGTH is 512 to fit the `AssetReference.name` column max
# `AssetReference.name` column max (String(512)) — otherwise a long-named # (`String(512)`) — otherwise a long-named asset would mint a cursor the same
# asset would mint a cursor the same server then refuses on the next request. # server then refuses on the next request.
# Cloud's data model has shorter names so its lower cap is fine there;
# cross-runtime byte-identity is unaffected because no real cloud cursor ever
# carries a value > 256.
MAX_ENCODED_CURSOR_LENGTH = 1024 MAX_ENCODED_CURSOR_LENGTH = 1024
MAX_CURSOR_VALUE_LENGTH = 512 MAX_CURSOR_VALUE_LENGTH = 512
MAX_CURSOR_ID_LENGTH = 128 MAX_CURSOR_ID_LENGTH = 128
@ -63,8 +56,6 @@ class CursorPayload:
order: str order: str
# Order direction tokens. Mirrored on the cloud follow-up so cursors carrying
# `o` are interchangeable between runtimes once both sides ship the field.
_VALID_ORDERS = ("asc", "desc") _VALID_ORDERS = ("asc", "desc")

View File

@ -1,10 +1,9 @@
"""Tests for app.assets.services.cursor. """Tests for app.assets.services.cursor.
The wire format must stay byte-identical with the cloud Go implementation The byte-identity fixtures below pin the wire format so a parallel Go
(common/pagination/cursor.go in Comfy-Org/cloud) so the frontend sees one implementation can mint exchange-compatible cursors for the same triple
contract across runtimes. The byte-identity fixture below mirrors the Go (asset name, value, id). Drift here would break frontend pagination
test cases any drift here means cloud and OSS minted different cursors against any compatible backend.
for the same triple, which would break FE pagination across backends.
""" """
from __future__ import annotations from __future__ import annotations
@ -187,9 +186,9 @@ class TestEncoderDecoderSymmetry:
""" """
def test_long_name_within_cap_round_trips(self): def test_long_name_within_cap_round_trips(self):
"""OSS assets allow names up to 512 chars (`String(512)`); cursor must """Assets allow names up to 512 chars (`String(512)`); the cursor
handle that. Cloud's lower cap is acceptable on its side because the encoder must round-trip a value at that cap so a freshly minted
cloud schema doesn't permit names that long.""" cursor never fails decode on the next request."""
long_name = "n" * MAX_CURSOR_VALUE_LENGTH long_name = "n" * MAX_CURSOR_VALUE_LENGTH
encoded = encode_cursor("name", long_name, "asset-x") encoded = encode_cursor("name", long_name, "asset-x")
payload = decode_cursor(encoded, ALLOWED) payload = decode_cursor(encoded, ALLOWED)
@ -269,10 +268,10 @@ class TestGoCompatJsonEscaping:
class TestByteIdentityFixtures: class TestByteIdentityFixtures:
"""Pin the wire format so it doesn't drift silently. """Pin the wire format so it doesn't drift silently.
NOTE these fixtures will need updates on the cloud side once cloud These fixtures hold the exact base64url-encoded bytes a given payload
mirrors the `o` (order binding) field. Until then, Python cursors and produces. Any change to the encoding (key order, escaping, ordering of
cloud cursors differ by exactly that key. The structural format (`s`, structural fields) will fail these tests loudly rather than diverge
`v`, `id` plus base64url + Go-compat escaping) remains aligned. silently from external consumers.
""" """
@pytest.mark.parametrize( @pytest.mark.parametrize(

View File

@ -1,8 +1,8 @@
"""Integration tests for cursor-based pagination on GET /api/assets. """Integration tests for cursor-based pagination on GET /api/assets.
Wire contract is shared with cloud's Go implementation (BE-893). These tests These tests exercise the handler/service/query path end-to-end;
exercise the handler/service/query path end-to-end; cursor-encoding-level cursor-encoding-level tests live in
tests live in tests-unit/assets_test/services/test_cursor.py. tests-unit/assets_test/services/test_cursor.py.
""" """
import time import time