Skip to content

Persistent API cache is shared across deployments: results from a restricted stack are served by a public one (and vice versa) #682

Description

@tkuhn

The persistent API cache (#570) is keyed by the query and its parameters alone — ApiCache.java:299, :309, :423 all use String cacheId = queryRef.getAsUrlString() — and the snapshot lives at a fixed path per home directory (~/.nanopub/nanodash-api-cache.ser plus its .d/ entry store, NanodashPreferences.getApiCacheFile). Neither the key nor the path mentions which registry or query service the result came from.

So every Nanodash process using the same home directory shares one cache, regardless of which services it is pointed at. This shows up as soon as an instance is pointed at a local/private deployment (#671):

  • Public results appear in a restricted instance. Observed while testing Support building upon restricted query service and recognize ProtectedNanopubs #671 against a local stack whose query service was still loading: all query calls failed with No healthy Nanopub Query instances available (94 of them in one session), yet the home page rendered a full set of pinned resources, latest nanopublications and active nanopublishers — restored from the snapshot, i.e. fetched earlier from the public network. The instance showed content its own deployment does not have.

  • Protected content persists into a public instance. This is the direction that matters. Retrieving a protected nanopublication from a local registry caches it (Utils.cacheNanopub / the nanopub cache is persisted too), and the snapshot is then read by whatever instance starts next with the same home directory — including one pointed at public services. Confirmed by finding the artifact code of a protected test nanopub inside ~/.nanopub/nanodash-api-cache.ser after a session against a local stack. Nanopublications typed npx:ProtectedNanopub are exactly the content that is meant not to leave a private deployment.

Suggested fix, in rough order of preference:

  1. Include the service identity in the cache location: derive the snapshot path (and the .d/ directory) from the configured registry and query URLs, so each deployment keeps its own cache and switching services cannot mix them.
  2. Or include it in the cache key, which fixes the mixing but still leaves protected results sitting in a file that another deployment reads.
  3. At a minimum, refuse to persist anything when ServiceMode.isRestricted() — the flag added for Support building upon restricted query service and recognize ProtectedNanopubs #671 — so protected content stays in memory for the process lifetime and never reaches disk.

Whatever the mechanism, an existing snapshot written by another deployment should be ignored rather than trusted, since the current file format carries no record of where its entries came from.

Note for anyone testing #671 locally in the meantime: point NANODASH_API_CACHE_FILE at a throwaway path, or the run will read and write the shared snapshot.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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