Skip to content

Add creator definition and requirements to record and protect creator#807

Open
csarven wants to merge 4 commits into
mainfrom
feature/creator
Open

Add creator definition and requirements to record and protect creator#807
csarven wants to merge 4 commits into
mainfrom
feature/creator

Conversation

@csarven

@csarven csarven commented Jul 19, 2026

Copy link
Copy Markdown
Member

This PR introduces the feature to record and protect the creator of a resource along with some privacy considerations.

This PR includes class 2 and 4 changes (Processing PRs):

  • #creator (class 4)
  • #server-description-resource-creator (class 4)
  • #server-protect-creator (class 4)
  • #creator-privacy (class 2)

Resolves #315 , #66


Preview

@SharonStrats

Copy link
Copy Markdown

This is great!

@csarven

csarven commented Jul 19, 2026

Copy link
Copy Markdown
Member Author

Implemented in dokieli (source code, code change)

@melvincarvalho

Copy link
Copy Markdown
Member

Some technical issues with the proposed requirements, in rough order of severity.

1. #server-protect-creator conflicts with #server-put-patch-auxiliary-resource.
The existing requirement states: "When a PUT or PATCH request targets an auxiliary resource, the server MUST create or update it." The new requirement states the server MUST NOT allow PUT/PATCH to update creator statements in a description resource and MUST respond 409. A server receiving a PATCH to a description resource that touches a creator statement cannot satisfy both MUSTs. The PR needs to amend the existing requirement to carve out the exception, or scope the new one so they compose.

2. "When a server wants to track…" is not a testable conformance condition.
A MUST predicated on server intent cannot be evaluated by a test suite — there is no observable distinction between "does not want to" and "wants to but fails to." Suggest either: (a) make it a MAY/SHOULD, or (b) condition it on an observable, discoverable server capability (e.g. advertised in the storage description).

3. The immutability guarantee is void under the deletion lifecycle.
Per #server-delete-remove-auxiliary-resource, deleting a resource deletes its auxiliary resources. Any agent with write access can therefore DELETE and re-PUT a resource, becoming its recorded creator. Meanwhile the original creator cannot correct or remove their own attribution (409). The mechanism is bypassable by exactly the parties it should constrain, and binding on exactly the party it should serve. If creator is intended as provenance, it needs to survive — or explicitly not survive — delete/recreate, and the spec should say which.

4. The privacy advisement has no conforming mechanism.
#creator-privacy says servers "can honour an agent's request … to have an existing attribution removed, for example, to meet data protection obligations." But #server-protect-creator forbids every HTTP write method from touching creator statements, and #creator defines the creator as unchanging. As written, honouring an erasure request (e.g. GDPR Art. 17) requires the server to violate a MUST NOT. The erasure path needs to be a defined, conforming operation, not an advisement that contradicts a requirement.

5. dcterms:creator is not a reserved predicate.
Description resources are the designated location for client-managed resource metadata, and dcterms:creator is in wide use meaning author — which routinely differs from the authenticated agent (apps writing on a user's behalf, uploads of third-party works, imported data). The requirement (a) overloads the predicate to mean "authenticated creating agent," and (b) as written, 409s any client statement using it, including pre-existing legitimate authorship metadata. Is the protection intended to cover all triples with predicate dcterms:creator, or only the server-asserted one? Either answer causes problems; a server-managed predicate (or a dedicated one, e.g. in the solid vocab) would avoid the collision.

6. For RDF sources the assertion is forgeable in the subject resource itself.
The protection covers only the description resource. A client can assert <> dcterms:creator ?x in the RDF source's own representation, which the server cannot reject on these grounds. A consumer merging the resource with its description resource (the normal use of describedby) obtains conflicting creator triples with no way to distinguish the server-asserted one. The guarantee doesn't survive the data model it's embedded in.

7. Minor points.

  • 409 (Conflict) implies a resolvable state conflict; refusing a categorically forbidden modification is 403 territory. (Noting the 409 appears to be carried over from #server-protect-containment, where containment triples live in a server-managed representation — a materially different situation from a client-writable description resource.)
  • Resources created via unauthenticated writes (public write access) record no creator, so consumers cannot rely on presence of the statement.
  • A storage migrated or restored to another server cannot reproduce existing creator statements without the target server violating #server-protect-creator.
  • The cited implementation (dokieli) is a client; both new requirements bind servers. Is there server implementation experience for the record-and-protect behaviour, per the class 4 designation?

@elf-pavlik

Copy link
Copy Markdown
Member

Can you please add HTML diff? I don't find raw RDFa diff to be something human readable 😵‍💫

Comment thread ED/protocol.html Outdated
<p about="" id="authorization-resources" rel="spec:advisement" resource="#authorization-resources"><span property="spec:statement">Servers are <span rel="spec:advisementLevel" resource="spec:Encouraged">encouraged</span> to use authorization techniques to prevent unwanted access to resources, rather than depending on the relative obscurity of their resource names.</span></p>
<p about="" id="identifiable-information-error-responses" rel="spec:advisement" resource="#identifiable-information-error-responses"><span property="spec:statement">To prevent leakage of non-resource data, servers are <span rel="spec:advisementLevel" resource="spec:StronglyDiscouraged">strongly discouraged</span> from including identifiable information in error responses.</span></p>
<p about="" id="webid-profile-privacy" rel="spec:advisement" resource="#webid-profile-privacy"><span property="spec:statement">The decision to include or exclude any information (e.g., storage, inbox) in a WebID Profile served from a Solid storage lies with the Agent controlling the WebID (or the URI owner). A URI allocated to a WebID in a Solid storage does not imply that the WebID is the storage owner. Owners of a WebID hosted from Solid storage are <span rel="spec:advisementLevel" resource="spec:Encouraged">encouraged</span> to consider information related to themselves that could be readable from other resources in the storage, even if that information (e.g., storage, inbox) is not part of the WebID Profile itself (see <a href="#storage-owner-uri-ownership">Storage Owner and URI Ownership</a> and <a href="#self-describing-resources">Self-describing Resources</a>.)</span></p>
<p about="" id="creator-privacy" rel="spec:advisement" resource="#creator-privacy"><span property="spec:statement">The <a href="#creator">creator</a> of a resource reveals information about an agent’s identity and activity. Disclosure of the creator through a description resource is subject to the same authorization rule as the subject resource. Servers are <span rel="spec:advisementLevel" resource="spec:Encouraged">encouraged</span> to minimise disclosure beyond what is necessary. Servers <span rel="spec:advisementLevel" resource="spec:Can">can</span> honour an agent’s request not to be attributed, or to have an existing attribution removed, for example, to meet data protection obligations.</span></p>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it mean that the use case of recording the creator without disclosing it to everyone who can read the subject resource remains unsolved?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I've clarified creator-privacy to be more concrete on what is intended, removed parts that were intentionally left open for features in the future, and added a bit on transparency.

Correct, that use case is not addressed. That's deliberate. Attribution is either recorded in the description resource and disclosed under the subject resource's authorization rule, or not recorded at all. Consistent with the Protocol.

This feature is for readers. Auditing or moderation by URI owners or server operators doesn't (particularly) require interop, since servers can keep internal records outside the protocol any way. Client-asserted authorship is forgeable, the server-asserted creator statement is not, and so the latter is trustable, and it's only useful if readers can see it. Disclosure to the resource's readership is the feature, not a side effect. This is a common practice e.g., commit log or wiki history.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://solidproject.org/TR/acp#matcher has acp:CreatorAgent

I recall commonly requested feature that access policies may have special case if agent is the creator of a resource. Would the intent be to have two separate mechanism for recording and disclosing the creator for the use case that this PR intends to satsify and for the use case of setting such access policies?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elf-pavlik, as I am interested in that functionality as well - I have to admit that I cannot follow your question.
How do you come to the conclusion that the would be two separate mechanisms for recording?

The authorization (for creator access) could simply look at the listed creator, captured via the here described mechanism, no? Am I missing something?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this proposal, if creator is recorded it is always disclosed to whoever has read access to the subject resource. So if Max creates a report in TAO's storage, description resource gets tao:report-x dct:creator foo:max ., then when TAO gives read access to SME they also end up disclosing that Max specifically created this report.
I see problem that recording the creator requires such disclosure and there is no flexible way to control how it gets disclosed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. Just pointing out that this is true also for all the other metadata (creation time etc).

Given the concrete proposal wording, I don't think that it is mandatory to record the creator of a resource and add it to the description resource. Therefore, I think it is also possible to simply record it but not put it in the description resource?

If you desire to decouple the access control lifecycle of the metadata from the primary resource then maybe -- for such use cases -- the description resource is not the best place for (to be private) metadata? Consider linking to another primary resource with that private meta data using rdfs:seeAlso from the description resource of the first primary resource.

I think a Server Implementation geared towards such privacy-critical use cases would be able to accommodate for such use cases even with the currently proposed wording.

Comment thread ED/protocol.html Outdated
<p about="" id="server-description-resource-max" rel="spec:requirement" resource="#server-description-resource-max"><span property="spec:statement"><span rel="spec:requirementSubject" resource="#Server">Servers</span> <span rel="spec:requirementLevel" resource="spec:MUSTNOT">MUST NOT</span> directly associate more than one description resource to a subject resource.</span></p>
<p about="" id="server-description-resource-authorization" rel="spec:requirement" resource="#server-description-resource-authorization"><span property="spec:statement">When an HTTP request targets a description resource, the <span rel="spec:requirementSubject" resource="#Server">server</span> <span rel="spec:requirementLevel" resource="spec:MUST">MUST</span> apply the authorization rule that is used for the subject resource with which the description resource is associated.</span></p>
<p about="" id="server-description-resource-creator" rel="spec:requirement" resource="#server-description-resource-creator"><span property="spec:statement">When a <span rel="spec:requirementSubject" resource="#Server">server</span> wants to track the <a href="#creator">creator</a> of a resource created by a successful request from an authenticated <a href="#agent">agent</a>, the server <span rel="spec:requirementLevel" resource="spec:MUST">MUST</span> include a statement with the <code>dcterms:creator</code> property, whose subject is the created resource and whose object is the authenticated agent, in the associated description resource.</span> [<a href="https://github.com/solid/specification/issues/315" rel="cito:citesAsSourceDocument">Source</a>][<a href="https://github.com/solid/specification/issues/66" rel="cito:citesAsSourceDocument">Source</a>]</p>
<p about="" id="server-protect-creator" rel="spec:requirement" resource="#server-protect-creator"><span property="spec:statement"><span rel="spec:requirementSubject" resource="#Server">Servers</span> <span rel="spec:requirementLevel" resource="spec:MUSTNOT">MUST NOT</span> allow HTTP <code>POST</code>, <code>PUT</code> and <code>PATCH</code> to update creator statements in a description resource; if the server receives such a request, it <span rel="spec:requirementLevel" resource="spec:MUST">MUST</span> respond with a <code>409</code> status code.</span> [<a href="https://github.com/solid/specification/issues/315" rel="cito:citesAsSourceDocument">Source</a>]</p>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would that work on description resources of containers? Some implementations don't allow to write statements on containers and only to description resources. This would lead to situation where on non containers client could set dcterms:creator but on containers only server managed creator would be possible.

@csarven csarven Jul 20, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dcterms:creator in description resources is server-managed, and client-asserted authorship can go in the subject resource's own representation. Clients can't set dcterms:creator on description resources of non-containers.

That said, the situation you describe arises from implementations that further restrict writes on container representations beyond what this spec requires. So, where clients can express metadata about a container is for them to resolve.

@uvdsl uvdsl left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my suggestions below.

Comment thread ED/protocol.html Outdated
Comment thread ED/protocol.html
<p about="" id="server-description-resource-max" rel="spec:requirement" resource="#server-description-resource-max"><span property="spec:statement"><span rel="spec:requirementSubject" resource="#Server">Servers</span> <span rel="spec:requirementLevel" resource="spec:MUSTNOT">MUST NOT</span> directly associate more than one description resource to a subject resource.</span></p>
<p about="" id="server-description-resource-authorization" rel="spec:requirement" resource="#server-description-resource-authorization"><span property="spec:statement">When an HTTP request targets a description resource, the <span rel="spec:requirementSubject" resource="#Server">server</span> <span rel="spec:requirementLevel" resource="spec:MUST">MUST</span> apply the authorization rule that is used for the subject resource with which the description resource is associated.</span></p>
<p about="" id="server-description-resource-creator" rel="spec:requirement" resource="#server-description-resource-creator"><span property="spec:statement">When a <span rel="spec:requirementSubject" resource="#Server">server</span> wants to track the <a href="#creator">creator</a> of a resource created by a successful request from an authenticated <a href="#agent">agent</a>, the server <span rel="spec:requirementLevel" resource="spec:MUST">MUST</span> include a statement with the <code>dcterms:creator</code> property, whose subject is the created resource and whose object is the authenticated agent, in the associated description resource.</span> [<a href="https://github.com/solid/specification/issues/315" rel="cito:citesAsSourceDocument">Source</a>][<a href="https://github.com/solid/specification/issues/66" rel="cito:citesAsSourceDocument">Source</a>]</p>
<p about="" id="server-protect-creator" rel="spec:requirement" resource="#server-protect-creator"><span property="spec:statement"><span rel="spec:requirementSubject" resource="#Server">Servers</span> <span rel="spec:requirementLevel" resource="spec:MUSTNOT">MUST NOT</span> allow HTTP <code>POST</code>, <code>PUT</code> and <code>PATCH</code> to update <a href="#creator">creator</a> statements in a description resource; if the server receives such a request, it <span rel="spec:requirementLevel" resource="spec:MUST">MUST</span> respond with a <code>409</code> status code.</span> [<a href="https://github.com/solid/specification/issues/315" rel="cito:citesAsSourceDocument">Source</a>]</p>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might I suggest to move this statement to #writing-resources for consistency in constraints on writing (on various types of resources incl. description resources)?

With that, #server-put-patch-auxiliary-resource could be amended to reflect the restriction stated here.

@csarven csarven Jul 21, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have an objection to that suggestion but perhaps worthwhile to back up briefly to be clear on the options:

  1. description resource includes the creator statement about subject resource (this PR)
  2. any RDF-bearing resource can have its own creator statement
  3. container resource includes creator statement about contained resources (i.e., adding dcterms:creator to #contained-resource-metadata-statements)
  4. use a link relation on the HTTP header of any resource

I think 2 is too limited (only RDF-bearing resources can carry it), and its provenance is the hardest to tell apart since the server-managed triple sits alongside client-authored content in the same graph.

4 is cheap(est) (HEAD), client has nothing to do with it, and would be aligned with the way owner works. However, I do worry that it adds more to the HTTP headers which may not be great long term.

1 and 3 can ensure that the creator statement for any resource can persist.

3 may be most consistent with the current spec.

If we start discovery from the subject resource, discovery of the creator statement is one additional GET either to the container resource or to the description resource. If we start discovery from the container, there is no additional GET. These cover different use cases.

3 discloses the creator to anyone that has access to the container but not to the subject resource itself.

I think we want 1 and/or 3 but 1 (this PR) is the right move.

Do you have a preference for the above 1-4 or another option?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

quick thoughts:

  1. this is absolutely fine!
  2. ... and those being (client-managed) statements are also fine - a client should keep provenance where statements came from to assess assertativeness anyway (i.e., the creator statement from (1) description resource should be considered assertative by clients (over those from the document itself, which might also be useful on their own - even if contradicting)
  3. I would not include creators of contained resources due to that breaking the access control binding of the creator statement to the primary resource.
  4. not a fan of too many link headers, to be honest...

So, I do prefer this PR (1) over the alternatives. I just think that the statement on modifying the description resource should go to the rest of the statements talking about the description resources. 🙂

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if the following is an adequate response to your comment:

I mentioned the above options because the current text and location is specifically about protecting creator in description resource. If we move it to the writing resources section, that might also cover the subject resource.

That brings us to the question of whether the creator of subject resource and description resource can be different and tracked. After all, the Solid Protocol allows agents to create description resources.

If we only track the creator of subject resource in the description resource, there is nothing else to change in the spec right now. If we later want to allow tracking of the description resource separately from the subject resource, we can introduce it generally to all resources under the writing resources section.

@uvdsl uvdsl Jul 22, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not looking at "creator of primary resource" vs "creator of description resource". That is not what I am after here.

I am looking at #server-put-patch-auxiliary-resource:

When a PUT or PATCH request targets an auxiliary resource, the server MUST create or update it. [Source]

which is clearly on the auxiliary resources, i.e., also about the description resource. By disallowing the update on the dcterms:creator in the description resource, you amend the above normative statement in my opinion. That is why I would keep the two statements close to each other in the spec at the very least...

@jeswr

jeswr commented Jul 20, 2026

Copy link
Copy Markdown
Member

This is a valuable piece of provenance to be capturing. In addition; I would suggest also providing a way for servers to capture the following:

  • The application used to author the document
  • Provenance of all (agent, application) pairs that have subsequently modified the document

@uvdsl

uvdsl commented Jul 22, 2026

Copy link
Copy Markdown
Member

Just noting that this functionality the server-internal recording of resource creators underlying this functionality could be useful for authorization as well, see e.g. solid/web-access-control-spec#139

@elf-pavlik

elf-pavlik commented Jul 22, 2026

Copy link
Copy Markdown
Member

Just noting that this functionality could be useful for authorization as well, see e.g. solid/web-access-control-spec#139

Wouldn't it make sense to design it in a way that recording it and having it for available for access control is independent from if/how it is disclosed to clients? Related to this thread #807 (comment)

I would be more comfortable if by default at least control mode was required to obtain creator information.

This PR doesn't inform who makes the decision if creator is recorded in the first place - implementer, deployment manager, server admin, storage owner, user. Having it recorded internally first and later adding standard process for the storage owner to manage disclosure would be my preference.

@uvdsl

uvdsl commented Jul 22, 2026

Copy link
Copy Markdown
Member

@elf-pavlik, to my understanding of this PR (@csarven, please do correct me), your comment is orthogonal to what both this PR and solid/web-access-control-spec#139 are about.

How exactly the creator of resources is recorded or where that information is stored in a Server is independent of the above issues. Today's Servers could/can already record the creator of a resource (which we did e.g. for MANDAT).

To my understanding, this PR aims to specify how a Server would indicate the creator of a resource -- if and when the Server records and (wants to <- not testable) indicates resource creators.
The issue of solid/web-access-control-spec#139 aims to specify how an authorization rule would specify that the creator of a resource is authorized to access that resource.

It is true that both of the above mechanisms use the underlying recording of resource creators by the Server.
And therefore, I shall correct my above comment to reflect that. Thank you for pointing this out.

Still, related to your other creator-recording question, I believe that this PR is just one way to indicate the resource creator based on an server-internal recording of resource creators. At the same time, there is no obligation to record creators at all -- or to store creators somewhere other than the description resource (if the Server so chooses). The PR and the WAC issue simply make no statement about that.

@elf-pavlik

Copy link
Copy Markdown
Member

Thanks for clarification! Having full human readable diff available would make this review easier #807 (comment)

I understand that this PR only intends to define the potential disclosure part by

  • registering dct:creator statements in Description Resource as exclusive server-only assertions
  • instructing cilents that server can assert creator in the Description Resource
  • leaving who and how controls disclosure of the creator out of scope

When a server wants to track the creator of a resource created by a successful request from an authenticated agent, the server MUST include a statement with the dcterms:creator property, whose subject is the created resource and whose object is the authenticated agent, in the associated description resource. [Source][Source]

I think the above would need to be adjusted, to don't assume if server tracks it or not but only if it wants to disclose it.

The next step IMO would be to look at possibly having a separate PR to specify requirement for server to track it, or not and maybe advertise this capability.
As well as looking at alternative proposals for when creator is tracked, how it could be disclosed and how this disclosure could be controlled - at least by the storage owner or agent with control over resource's access.

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

Projects

Status: Drafting Phase

Development

Successfully merging this pull request may close these issues.

Define creator

6 participants