Skip to content

0.6.0

Latest

Choose a tag to compare

@adamtheturtle adamtheturtle released this 18 Jul 18:03
bd81008

URL-correctness and credential-scope fixes, plus the PaginatedRESTClient 0.2.0 bump. Each fix carries a regression test verified to fail without it.

Fixed

  • Path segments are no longer double percent-encoded (#10). pathSegment escaped an id and URL.appending(path:) escaped it again, so ada+test@example.com was requested as ada%252Btest%2540example.com — the server saw a literal ada%2Btest%40example.com and 404'd, or addressed a different record. SCIM /Users/{id} was the most likely trigger, since many deployments use the email as the resource id. Every URL now goes through one funnel that never re-encodes. The old suite used only bare ids like t1, which is why this was invisible.
  • A single malformed SCIM row no longer empties the directory (#11). The try? wrapped the array rather than the element, so one numeric id where a String? was expected made scimUsers()/scimGroups() return an empty list — with no error and no log line — for a fully populated directory. Now decodes leniently per element, like the other list endpoints.
  • + is now escaped in search queries (#12). URLComponents leaves + literal, and the Rack/Rails backend decodes it as a space, so C++ and plus-addressed emails were searched for as something else entirely.
  • allUsers no longer duplicates a user when a row is dropped (#13). Fan-out offsets were derived from the decoded count, but the server pages by requested limit — so one malformed record shifted every subsequent offset and returned a user twice, feeding duplicate keys to a SwiftUI ForEach. Offsets now come from the page size.
  • The Bearer token is no longer sent to a foreign host (#14). cursorURL returned any absolute URL from a server next field unvalidated, and authorizedGET attaches the credential unconditionally — so a response naming another host received the user's personal access token. Cursors are now constrained to baseURL's origin (scheme, host, port), and anything else is rejected.

Upgrading

PaginatedRESTClient is now 0.2.0. HackerRankPage's Item is constrained to Identifiable so each page can supply a stable identity and keep the parallel fetch path — source-breaking in principle, though all ten item types already conformed. pageSize is declared as the API's documented maximum of 100, sourced from the same constant every request already sends as its limit, so the two cannot drift.

Full changelog: 0.5.0...0.6.0