fix(apikey): a scope target is not always in universeIds - #38
Merged
Conversation
The post-create check announced that a scope had not been stored on its
universe, and that the same scope had appeared unasked on `*`, for a key
Roblox had stored exactly as requested. The two warnings mirrored each
other, which is the signature of a target that was not read rather than a
permission that was not stored.
Roblox returns targets under at least three field names, and which one
follows the scope: `universeIds` for `universe` and
`universe-datastores.control`, `universeDatastores: [{universeId}]` for
`universe-datastores.objects` and `.versions`, `groupIds` for a
creator-targeted scope such as `asset`. That is why one key carried both
the bug and its counter-example. The reader took `universeIds` alone, and
a scope whose target it could not find fell through to the `*` that means
"no target at all", which produced the second warning.
Cosmetic in effect, not in consequence: the check exists to catch a key
that cannot do its job, and one that cries wolf on a correct key is how a
real warning gets ignored.
A target under a field this build does not know is now reported rather
than read as a wildcard. That is the rule the module already applied to an
unreadable entry, and the reason is the same one written at the top of it:
what makes this class of bug survive is a reader that turns "not
understood" into a confident wrong answer. A fourth shape now surfaces as
"this build cannot read the answer".
The same guard covers a data store named inside the target. A key scoped
to one store is sent with two target parts, no capture shows how that
comes back, and dropping the name would verify a narrow key against a wide
request and call it a match.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #37.
The report is exact, including the diagnosis.
IntrospectScopereaduniverseIdsand nothing else, and a scope whose target it could not find fell through to the*thattarget_partsuses for "no target at all". That is what produced the mirrored pair: missing on the universe, unasked on*.The three shapes
universeIds: [id]universe,universe-places,universe-datastores.controluniverseDatastores: [{universeId}]universe-datastores.objects,.versionsgroupIds: [id]assetG<id>, the spelling it was sent withuserIdsis handled the same way asgroupIds. No capture shows it, but a creator target is sent asU<id>, and the guard below catches the spelling if it turns out to be another.Ids are read whether they arrive as a string or a number. That is the same target written differently rather than a shape nobody understands, and refusing it would skip the verification over punctuation.
The part that is not about these three fields
The bug is not really "one field was missing". It is that an unread target became a confident wrong answer, which is the failure already written at the top of this module:
filter_map(...ok())turning "not understood" into "this key grants nothing".So a non-empty array under a field name this build does not know is now an error, not a wildcard. A fourth shape surfaces as
introspect answered in a shape this build cannot readand the verification is skipped, which is honest. Scalars and empty arrays are left alone: refusing to verify a key over an extra boolean would be the same overreach pointing the other way.That error reaches nothing that can fail a command.
createprints it and returns, anddiagnostics::introspect_scopesalready documents itsErras "unavailable", not "broken".What this does not fix
A key scoped to a named data store is sent with two target parts,
[universe_id, name]. Nothing shows how that comes back. The same guard reports it asuniverseDatastores[].datastoreNamerather than dropping the name, because dropping it would verify a narrow key against a wide request and call it a match. So those keys move from a false green to no verification. If one can be created against live Open Cloud, that response is a few lines to add.Worth flagging separately:
permissions()treats every entry oftarget_partsas its own target, so a two-part datastore target is already counted as two. Left alone here, but it means a "target" is not quite the same thing on both sides of the comparison.Tests
The fixture is the response from the issue, with the counter-example the same key carried.
universeDatastorestarget is the universe it names, not*controlandobjectsentries of one key agree on their universegroupIdstarget is restored toG<id>, anduserIdstoU<id>Plus one at the
createlevel that runs the issue's request against the issue's response and asserts both warning lists are empty.