solid / type-indexes

About Type Indexes and how they can be used by Solid developers.
https://solid.github.io/type-indexes/
MIT License
7 stars 3 forks source link

Changing access of indexed resources from private to public (and vice versa) #25

Open elf-pavlik opened 1 year ago

elf-pavlik commented 1 year ago

It seems that public and private type indexes, instead of just indexing resources partition them. I will describe it based on Type Registration using solid:instanceContainer predicate.

Let's take snippets from the current draft, I will exchange Bookmark with Photo to work with something more straight forward. first the public type index https://solid.github.io/type-indexes/#public-type-index

 @prefix solid: <http://www.w3.org/ns/solid/terms#>.
                    @prefix vcard: <http://www.w3.org/2006/vcard/ns#>.
                    @prefix ex: <http://ns.example/#>.

                    <>
                      a solid:TypeIndex ;
                      a solid:ListedDocument.

                    <#ab09fd> a solid:TypeRegistration;
                      solid:forClass vcard:AddressBook;
                      solid:instance </public/contacts/myPublicAddressBook.ttl>.

                    <#bq1r5e> a solid:TypeRegistration;
                      solid:forClass ex:Photo;
                      solid:instanceContainer </public/myPhotos/>.

second the Private Type Index https://solid.github.io/type-indexes/#private-type-index

@prefix solid: <http://www.w3.org/ns/solid/terms#>.
                      @prefix vcard: <http://www.w3.org/2006/vcard/ns#>.
                      @prefix ex: <http://ns.example/#>.

                      <>
                        a solid:TypeIndex ;
                        a solid:UnlistedDocument.

                      <#ab09fd> a solid:TypeRegistration;
                        solid:forClass vcard:AddressBook;
                        solid:instance </private/contacts/myPrivateAddressBook.ttl>.

                      <#bq1r5e> a solid:TypeRegistration;
                        solid:forClass ex:Photo;
                        solid:instanceContainer </private/myPhotos/>.

Let's imagine adding a cat photo into the private type index (partition). We could get something like /private/myPhotos/garfield

At some point, the resource owner wants to make a public post and just that photo in it, so they decide to change ACL/ACR controlling access to that specific photo and make it public read.

Since type indexes effectively partition, not just index the resources. We would end up with Private Type Index leading to / indexing / containing a public read photo.

Exactly the same situation can happen the other way if the photo was initially made public and created at /public/myPhotos/garfield. Once the resource owner changes that access policy to that photo, we end up with a mismatch where a Public Type Index leads to / indexes/ contains a private photo.

To avoid those mismatches, the resource owner would have to delete the original resource and create it under a different IRI, which goes against the permanence of IRIs. It also doesn't fit well with access control, which allows simply changing access to any given resource.

jeff-zucker commented 1 year ago

Putting an instanceConatiner pointer to /foo/photos/ in the privateTypeIndex does not make an assertion that the container or resources in it are private. It asserts, that apps/users with access to the privateTypeIndex can learn about where the container is located and the type of things it contains.

If the access of /foo/photos/garfield.png changes, that would not necessitate any change to the privte typeIndex. People with access to the privateTypeIndex can still learn that there are photos in /foo/photos/.

elf-pavlik commented 1 year ago

My general point is that type indexes take a very brittle approach and don't align very well with access control which allows for changing access to the given resource at any time.

If the access of /foo/photos/garfield.png changes, that would not necessitate any change to the typeIndexes. People with access to the privateTypeIndex can still learn that there are photos in /foo/photos/.

I agree that in cases where resource access changes from public to private it is easier to find a workaround. The app which has access to both private and public indexes, could:

Above sounds to me like bending backward just to use type indexes.

There is still the potential of using a potentially embarrassing filename as part of the resource URI. Later changing access to the resource itself from public to private just to have the embarrassing filename still listed in the public type index.

When it comes to changing access from private to public. Even bending backward wouldn't help, since the app only having access to the public type index will not be able to find a photo that was made public if it was originally listed in the private type index.

jeff-zucker commented 1 year ago

It seems to me that this issue could be handled in a non-normative consideration, something along the lines of ;

Triples using the solid:instanceContainer predicate in the publicTypeIndex should be used with caution and may result in exposing the names and sizes of resources you later make private. Instead, in cases where this might be an issue, you may wish to use only solid:instance predicates which can be added and dropped individually or instead point to an index page (e.g. point to an ex:PublicPhotoAlbum rather than to an ex:Photo).

elf-pavlik commented 1 year ago

I'm afraid that recommending using solid:instance instead of solid:instanceContainer doesn't sound like an actual solution. Since Solid uses resource-level access control, describing everything in one big resource takes away the potential of granular access control which is available when a container is used with one resource describing each thing.

If using solid:instance is such a great approach, why the spec even introduces solid:instanceContainer which comes with the problem I intended to capture in this issue?

I believe we all agree that the spec readers (hopefully implementers) deserve to be informed about all known issues and the consequences they should anticipate. My intention here is to clarify the problem and find the best way to clearly communicate it in the spec.

NoelDeMartin commented 1 year ago

I didn't understand type indexes like that, is there some part of the current draft suggesting that? I understand the private/public distinction of the type indexes to apply only to the type index itself (after all it's called "public type index" not "type index of public resources").

So for example, I could have a single container with all my pictures, both private and public, and I would advertise it in the public type index. Then, when a client is reading that container they would get all the resources or only the private ones depending on their permissions.

elf-pavlik commented 1 year ago

So for example, I could have a single container with all my pictures, both private and public, and I would advertise it in the public type index.

In that case, what is the purpose of a private type index?

Then, when a client is reading that container they would get all the resources or only the private ones depending on their permissions.

To stay clear, they would get all the ldp:contains statements, no matter how many of the contained resources they can access. That includes mentioned private contained resources with potentially embarrassing filenames used as part of their URIs.

The problem I'm trying to pinpoint is related to the type index linking to type registrations, which in turn with their associated solid:instanceContainer partition contained resources.

I don't think I'm the only one who finds it confusing to have:

In the matter of fact, no resource is public or private in some fundamental way. Any resource at any time can have its access control set to public and at any other time set to private. "Indexing" them by creating them in a public or private container is destined to fail.

I guess this approach might be some iteration on http://www.w3.org/ns/pim/space

ws:PublicWorkspace :comment "Aceess is open to the public. Anything in a public workspace can be accesed by anyone.";

ws:PrivateWorkspace :comment "Access only by the you, the user.";

Both sound to me like "workspace with public resources" and "workspace with private resources".

NoelDeMartin commented 1 year ago

In that case, what is the purpose of a private type index?

My idea was that the purpose is to advertise publicly or privately where things are stored, I'm not making any assumptions on why apps would decide to do one or the other.

I can come up with an example, though. I could have a container with both private and public documents, but I don't want all the documents in that container to be discoverable. Still, the ones that are public should be readable by anyone with the link.

That's actually a real use-case with my app Umai. You can share "unlisted" recipes; which are public for anyone who has the link, but not discoverable otherwise. Similar to unlisted videos in Youtube. That's why my app only declares a private type index, not a public one.

Even having said that, I don't think we can always come up with use-cases and examples for everything. There will always be someone using a technology in a way that we didn't anticipate. That's why I think it's important to clarify in the spec what type indexes are actually supposed to be. And so far, my understanding is that the private/public distinction only applies to the indexes themselves, not to anything they are indexing.

To stay clear, they would get all the ldp:contains statements, no matter how many of the contained resources they can access. That includes mentioned private contained resources with potentially embarrassing filenames used as part of their URIs.

I'm not sure if this has been discussed elsewhere, maybe https://github.com/solid/specification/issues/227?

But my opinion in that case is that a container should not advertise the private documents, for the reasons you just mentioned. I don't think that issue is related with the type index.

In the matter of fact, no resource is public or private in some fundamental way. Any resource at any time can have its access control set to public and at any other time set to private. "Indexing" them by creating them in a public or private container is destined to fail.

I agree, that's why I'm saying that when we say "public" or "private", we are only talking about the type index, not about the indexed documents/containers. If we were, they should be called "type index of private resources" instead of "private type index".


By the way, I have to say I agree with many of the concerns and limitations of type indexes, I don't think they are perfect by a long shot. But as I said a while ago "I’d much rather have a something that works in practice, than being caught up in theoretical discussions that never become a reality".

elf-pavlik commented 1 year ago

Thank you @NoelDeMartin, I find your examples very helpful! I would like to ask you about one more scenario from your use case.

That's actually a real use-case with my app Umai. You can share "unlisted" recipes; which are public for anyone who has the link, but not discoverable otherwise. Similar to unlisted videos in Youtube. That's why my app only declares a private type index, not a public one.

Let's say that the user with such "unlisted" recipes or videos would like to make one/some of them listed. Could they do it with private & public type indexes without the need to change the URIs of those recipes/videos going from "unlisted" to "listed"?

timbl commented 1 year ago

The only way I have used type indexes to have them point to a not a photo or a collection of photos but something like a Tracker which manages lots of issues, or an AddressBook which handles groups and people, or a chat, where lots of messages have the same access control.

In the Address Book case, for example, the App manages access control. The app can do complicated things like giving access to a Card as function of which groups it is in and whoo has access to those groups. In general, the app deals with the complexities of sharing things in different ways. Its simpler when all the address cards in the book have the same access, of course and a common case. But the Address Book or books which you put inthe type indexes you put in as a function of whether you want to allow other people to see them in your profile, or just keep of track of them yourself.

This is the UI for the type index on my own contacts., in the Tool panel of the AB. It talks about whether I want public links not whether the book itself is public.

Screenshot 2023-08-02 at 15 48 12

(The other two project checkboxes are for communities I am a member of, so I can share there too if I like.)

elf-pavlik commented 1 year ago

The app can do complicated things like giving access to a Card as function of which groups it is in and whoo has access to those groups. In general, the app deals with the complexities of sharing things in different ways.

Can I find it documented somewhere in detail? I mostly want to understand how the app can do it, especially since each user can choose to use a different app so the actual access policies need to be record independent of any app. In SAI, there is an Authorization Agent which deals with all the complexities of sharing (setting access policies) which later are captured as Access Authorization and Access Grant for the agent acting as a grantee. Since currently, solid authorization doesn't support those Access Grants directly, they can be translated to ACP and reflected in ACRs of corresponding resources.

NoelDeMartin commented 1 year ago

Let's say that the user with such "unlisted" recipes or videos would like to make one/some of them listed. Could they do it with private & public type indexes without the need to change the URIs of those recipes/videos going from "unlisted" to "listed"?

No, they couldn't :(. And this is one of the limitations I agree with.

The way I've solved it in my app, is that what I'm listing on the public type index is not a container, but a link to a list of recipes (a link to a schema:ItemList to be more precise). Which has the drawback that the list is indexed as a generic "item list", there is no way from the type index to know if it's a list of recipes or something else.

I could also have listed the individual recipes, but I decided to do it like this because that way I can also add some metadata to the list itself, not just the invidual recipes (such as the title, the author, a description, etc.)

elf-pavlik commented 1 year ago

I see #26 which might be at least partially in response to this discussion.

timbl commented 1 year ago

See a clarification https://github.com/solid/type-indexes/pull/26 about how type indexes are used in practice. A RecipeManger could be the main thing including lists and recipes in the stuff it manages. And could be in s type index. And could RecipeList subclass if List. So @NoelDeMartin you could flag the list as being a Recipe List to drive handlers and icons in list of stuff.

timea-solid commented 1 year ago

Interesting conversation. It makes me think of a use case document additional to the spec.
What do you think?