Challenges With Syncing Read Access Between AppViews and Space Hosts

Continuing the discussion from Permissioned data proposal discussion:

I was looking at simplespace and the managing app and something occurred to me that might be worth discussion.

Yesterday while talking with @meri.garden it came up that we have something of a tricky situation for AppViews when a space is configured with an arbitrary or dynamic read policy.

Essentially every AppView that indexes private data is tasked with the sensitive job of replicating the space host’s read-access boundaries over the indexed data.

If you can’t get a space credential, then hypothetically an AppView should not serve you any indexed data from that space. So we either need to:

  1. Have all queries to the AppView contain a list of space credentials that may be used to prove access to data in the index that originated from the list of spaces, or
  2. Have the AppView’s query replicate the read-access check that the space host would perform before it returns results from its index.

Option 1 doesn’t really work in practice because you could have access to thousands of spaces in a group, and it would be ridiculous to have to individually obtain a space credential to each one of them before you could make a query to the AppView that may include them. For example, I could join a Roomy space and there could be thousands of threads, each of which are a permissioned space, and I would have to get a space credential for each of them, just to view the aggregated list of threads and their titles on our thread list page.

Option 2 is tricky because it requires that the AppView understand and accurately reproduce the logic that the space host would apply before giving out access. For example, if access to spaces is determined by the presence of records in the group’s PDS account, as the opensocial proposal was considering, then it would be possible for the AppView to subscribe to the role and membership records, sync those to its database, and then use that info as a part of its SQL queries to make sure that the right users get the right results.

This is somewhat sensitive because if the AppView gets it wrong, then it might allow people to read things they aren’t allowed to, but I think that is just the nature of the problem and essentially unavoidable at this point.

What becomes a bigger problem is when you have an arbitrary or dynamic read access policy, such as when a simplespace uses a managing application. The managing application is allowed to make any kind of judgement at any time as to whether or not you are allowed to access a certain space in the managed group. This leaves the AppView completely in-the-dark on how to protect records, unless you go back to option 1 and require each query to justify its access with valid space credentials.


I’m opening the discussion to try and get more perspectives on this difficulty and how we expect it to be handled in practice.

To me it seems that if we define read access standards based on sync-able records, then the AppView can probably reasonably implement that standard in its database queries and it “just” has to cache and keep the source records up-to-date.

Alternatively, maybe we need a sync protocol and write notifications of some sort for access changes, so that AppViews can reasonably be expected to keep in sync with the space host?

An extra challenge is that the space host itself may not even know what access a user has before actually querying external services. For example, what if you have a space where the managing application allows all contributors to a particular GitHub repo access to it?

Delegating auth to other services is powerful and effective at a protocol layer, but when it comes to the AppView needing to reflect an up-to-date view of that access, it seems pretty difficult to do properly.


Related to this is the fact that I’m developing a space host with the arbiter that allows fully arbitrary polices, which would run into the same problem as simplespace + a managing application above.

One thought I had is that maybe what we should aim for most of the time is having well-defined and standardized read access rules, based on replicate-able records, but write access rules, on the other hand, can be arbitrary without issue because they are centralized and only apply to the space host itself and the group’s own repos.

That’s just a general design idea for making it easier on AppViews as much as possible, while still allowing for more customizable forms of governance. The AppViews only need to worry about replicating the read access, while the space host can do whatever it wants to determine who is allowed to change the records that determine who has what read access.


Anyway, I would definitely like to hear if anybody else has thoughts on this.

1 Like

I think you are putting your finger on one of the less-intuitive parts of permissioned data spaces: the protocol itself is very flexible about how read and write access is granted, pushes most of those decisions to “application/modality layer”, and thus app services (like appviews) need to implement all this logic themselves.

As one example, the “bulletin.my” demo app uses public bsky follow relationships to determine visibility. In fact, using the simplespace managing service mechanism, the space host is asking the application what the visibility should be, not the other way around. And in that case, the application needs to index public repo records, not just space records, to make the decision.

I think the opensocial.community system will provide some common structure for this, so that every app doesn’t need to reinvent all this from scratch. Maybe there will end up being software libraries which help implement that particular set of visibility rules.

I don’t think I would frame this as a difficulty or additional work for most apps: this is just what implementing an app service with limited visibility has always entailed. In this case you might be synchronizing distributed data to inform that logic, but the logic is basically the same.

I do think there will be some complex cases:

  • Imagine a closed forum app which allows embedding content from other forums. Users A and B might both in Forum One, and users A, B and C in Forum Two. User A could make a post in Forum One, User B sees it, and embeds it in a separate post in Forum Two. When users A and B see that wrapping post, they “could” see the original post; but should user C be allowed to see it? Is the answer the same at app-layer and protocol-layer? I think this is maybe a question for the modality designer to answer.
  • If you implement multi-modality functionality in an app (eg, embedding non-public content from other space types), you might need to implement all the visibility logic (and indexing) from the “other” apps. This could add a lot of friction around adding multi-modality features. I wonder if calling APIs from an implementation of the “other” apps would be a common solution (haven’t thought it through all the way).
  • Trying to implement modality-generic functionality becomes hard. Eg, if you want to implement generic infrastructure like microcosm, and somehow granted it broad access to many types of space data for many users, then that service would not have any knowledge about which accounts should be allowed to see (or query, or aggregate) which data.

That last point is true even for “public” space data, because there isn’t a unified way to know which spaces are public or not (or when).

1 Like

That’s an interesting way to do it that I hadn’t thought of![1] Just making the AppView the “on protocol” authority does make it very easy for the “blessed” AppView, but not any easier if someone wants to use another AppView. Still a useful pattern.

Yeah, I think this is mostly just something to be aware of when making group standards like opensocial, etc. that other apps are going to implement.

The catch that I was realizing is that using a managing app which could use any means for informing auth decitions means that “synchronizing distributed data” is not guaranteed to be easy or even possible.

But that is a freedom that makes total sense and should be maintained at the protocol layer. The matter of whether or not one or more AppViews can feasibly keep in sync with the on-protocol permissions is definitely a concern for the standards we build on top of permissioned spaces.


  1. Recently anyway. I’m just remembering that was the original plan before we came up with the arbiter to act as a permission gateway that wasn’t specific to a particular AppView. ↩︎