Pagination tokens have been a bane to my existence. I'm basically this backend engineer. Have done these exact steps. Between worry the frontend will decide and annoyance at explaining how tokens work, I am growing to hate working with frontend teams.
Even worse, when I have to explain that they may get an empty result with a token meaning they need to call again. Unbounded service call means nothing, it seems.
Looks pretty cool, however, I'm curious about the usage of a pointer to the key slice. A slice is just two ints and a pointer, so the copy semantics is pretty cheap, and one less pointer for the GC to clean up later.
Is there some reason why you choose to pass a pointer to the slice?
“intellectual curiosity of your coworkers demands they base64-parse it.” This is crazy behavior. Creating your own pagination key, assuming it exists, and then putting that in production certainly proves “Hyrum’s law”.
I have a similar story to OP's. I had made a service that provided access to cryptographic keys but did not reveal the key material directly. Instead it had an API for requesting a key "handle" for the key you wanted to use, and API for performing operations like encrypt and sign that took that key handle and performed the operation inside the service. The key handle was to be treated as opaque and implemented as a base64-encoded blob containing the key ID and a signature (for tamper-proofing).
One day a coworker working on another project that would use my service contacted me to complain that the keys from my service were malformed. Turned out they had noticed that the return value was base64-encoded so they assumed it was a base64-encoded key, so they wrote code to base64-decode it and load the result into their language's crypto library to perform those operations directly.
To remove/obscure structure from a token so that the structure is not relied upon & can be changed in backwards incompatible ways without disrupting API consumers.
If you think it's internal details are too simple to justify a dependency, you can vendor or reimplement it, but that's orthogonal to whether it's pointless. The README is pretty detailed & explicit about what the point is.
Pagination tokens have been a bane to my existence. I'm basically this backend engineer. Have done these exact steps. Between worry the frontend will decide and annoyance at explaining how tokens work, I am growing to hate working with frontend teams.
Even worse, when I have to explain that they may get an empty result with a token meaning they need to call again. Unbounded service call means nothing, it seems.
Kudos on this project!
Looks pretty cool, however, I'm curious about the usage of a pointer to the key slice. A slice is just two ints and a pointer, so the copy semantics is pretty cheap, and one less pointer for the GC to clean up later.
Is there some reason why you choose to pass a pointer to the slice?
You're correct about slice semantics but key here is actually a Go array, not a slice. So it's passing a pointer instead of an entire array.
Ahh, thank you. Still very new to go :)
“intellectual curiosity of your coworkers demands they base64-parse it.” This is crazy behavior. Creating your own pagination key, assuming it exists, and then putting that in production certainly proves “Hyrum’s law”.
I have a similar story to OP's. I had made a service that provided access to cryptographic keys but did not reveal the key material directly. Instead it had an API for requesting a key "handle" for the key you wanted to use, and API for performing operations like encrypt and sign that took that key handle and performed the operation inside the service. The key handle was to be treated as opaque and implemented as a base64-encoded blob containing the key ID and a signature (for tamper-proofing).
One day a coworker working on another project that would use my service contacted me to complain that the keys from my service were malformed. Turned out they had noticed that the return value was base64-encoded so they assumed it was a base64-encoded key, so they wrote code to base64-decode it and load the result into their language's crypto library to perform those operations directly.
This looks like a very simple wrapper around golang.org/x/crypto/nacl/secretbox
What’s the point of this?
To remove/obscure structure from a token so that the structure is not relied upon & can be changed in backwards incompatible ways without disrupting API consumers.
If you think it's internal details are too simple to justify a dependency, you can vendor or reimplement it, but that's orthogonal to whether it's pointless. The README is pretty detailed & explicit about what the point is.