Skip to content

Standard and advanced Model Target datasets are interchangeable across route families #3393

Description

@adamtheturtle

What happens

ModelTargetDataset records whether it is standard or advanced:

dataset_type: ModelTargetDatasetType

but nothing checks that field again. Datasets are stored in one flat dict keyed by UUID (TargetManager._model_target_datasets), and the status, download and delete handlers look the UUID up without regard to which route family the request came in on.

So a dataset created as standard is fully reachable through the advanced routes:

created standard dataset:      201
status via standard route      -> 200
status via ADVANCED route      -> 200
download via standard route    -> 200
download via ADVANCED route    -> 200
DELETE via ADVANCED route      -> 200
status after cross-type delete -> 404

The last two lines are the sharpest version: a dataset created at POST /modeltargets/datasets is deleted by DELETE /modeltargets/advancedDatasets/{uuid}.

The eight routes are therefore four routes with two spellings each. dataset_type is used at creation time, for _model_count_details and for the advanced-only model count limit, and then never again.

Why it matters

Real Vuforia treats these as separate resources. They have separate documented OAuth scopes — modeltargets.standardmodeltarget.all and modeltargets.advancedmodeltarget.all, listed in #3345 — and #3202 records that real Vuforia rejects an unscoped client at /modeltargets/advancedDatasets with a 403 before validating anything. A standard-only client asking the advanced endpoint about its own dataset is not going to get a 200.

The consequence for users is the specific failure a verified fake exists to prevent: code which polls or deletes via the wrong endpoint family passes against the mock and fails against real Vuforia, and the mock gave no signal.

Relationship to existing issues

Not covered by the open Model Target issues, which I checked before filing:

  • #3194 is about the shape of the status response body and the status lifecycle.
  • #3195 is about the realism of the downloaded zip.
  • #3196 is about adding verified fake coverage for advanced create/status/download/delete — it would exercise advanced datasets through advanced routes, so it would not catch cross-type access.
  • #3345 and #3192 are about tokens and scopes rather than resource identity.

Scoping by token would partly mask this once #3345 lands, but only for clients which lack the advanced scope. A client holding both scopes would still be able to delete a standard dataset through the advanced route.

Suggested resolution

Check dataset_type in the status, download and delete handlers and return a not-found error when it does not match the route.

What the not-found error looks like should be checked against real Vuforia rather than guessed — the mock already has a Vuforia-shaped unknown-dataset error using userId:mock as the target, so reusing that is the obvious first guess, but whether real Vuforia gives 404 or 403 here depends on scope checking happening first.

A test for this fits naturally into #3196: while adding advanced-route coverage, assert that a standard dataset is not visible through the advanced routes and vice versa.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions