Both list_documents (documents/list.rs) and list_grants (sharing/list.rs) have identical pagination loops: paginate listRecords, deserialize each record, check schema version, map to entry struct. Extract a generic list_records_typed function into client/ that handles the pagination+parse+version-check, then refactor both callers. The mapping closure converts (uri, parsed_record) -> entry. Need a HasVersion trait or similar to access the version field generically. Tests: test the generic function directly with a mock record type.
Both list_documents (documents/list.rs) and list_grants (sharing/list.rs) have identical pagination loops: paginate listRecords, deserialize each record, check schema version, map to entry struct. Extract a generic list_records_typed function into client/ that handles the pagination+parse+version-check, then refactor both callers. The mapping closure converts (uri, parsed_record) -> entry. Need a HasVersion trait or similar to access the version field generically. Tests: test the generic function directly with a mock record type.