Introduction

This specification refines the semantics and interaction patterns of the Linked Data Platform ([[LDP]]) in order to better serve the specific needs of those interested in implementing repositories for durable access to digital data. Additionally, this specification contains:

The goal of this specification is to define the behaviors of Fedora server implementations in order to facilitate interoperability with client applications. Although Fedora servers are not necessarily drop-in replacements for one another, a client developed against this specification should work against any Fedora server with little modification. Client applications should not expect the behaviors of every Fedora server implementation to be identical, but the interaction patterns defined in this specification should provide a sufficient mechanism to navigate the differences between Fedora server implementations.

This document is version 1.0 of the Fedora API specification. Release follows a period of review and implementation based on the Candidate Recommendation of 25 June 2018, with minor changes.

A conforming Fedora server is a conforming [[!LDP]] 1.0 server that follows the additional rules defined in sections , , , and of this specification.

Terminology

Terminology is based on W3C's Linked Data Platform 1.0 [[!LDP]], Memento [[!RFC7089]], and Web Access Control [[!SOLIDWEBAC]].

ACL:
An Access Control List Resource is a resource providing a set of authorization statements as defined in [[!SOLIDWEBAC]] Access Control List Resources.
LDPR:
A Linked Data Platform Resource as defined in [[!LDP]]. This may be an LDP-RS or an LDP-NR.
LDP-RS:
An LDPR whose state is fully represented in RDF as defined in [[!LDP]] Linked Data Platform RDF Source.
LDP-NR:
An LDPR whose state is not represented in RDF as defined in [[!LDP]] Linked Data Platform Non-RDF Source.
LDPRv:
An LDPR that is simultaneously a Memento URI-R and a Memento TimeGate.
LDPRm:
An LDPR that is simultaneously a Memento URI-M.
LDPC:
A collection of linked documents or information resources as defined in [[!LDP]] Linked Data Platform Container.
LDPCv:
A version container: an LDPC that is simultaneously a Memento TimeMap.
LDP-contained:
The relationship binding an LDPC to LDPRs whose lifecycle it controls and is aware of as defined in [[!LDP]] Containment.
URI-R:
A type of versioned resource defined in Memento [[!RFC7089]] section 1.2.
URI-M:
A type of resource that is defined in Memento [[!RFC7089]] section 1.2 as representing a version of a given URI-R.
TimeGate:
A type of resource defined in Memento [[!RFC7089]] section 1.1 providing Accept-Datetime-varied negotiation of versions of an URI-R.
TimeMap:
A type of resource defined in Memento [[!RFC7089]] section 1.1 that contains a machine-readable listing of URI-Ms associated to a given URI-R.

Conventions used in this document

The following namespace prefixes are used in this document:

@prefix acl:     <http://www.w3.org/ns/auth/acl#> .
@prefix foaf:     <http://xmlns.com/foaf/0.1/> .
@prefix ldp:     <http://www.w3.org/ns/ldp#> .
@prefix rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

Resource Management

Non-normative note: This section defines the core operations for managing content, using [[!LDP]] as a baseline. It extends [[!LDP]] in several ways, including making some optional features mandatory and expanding requirements related to binary content.

[[!LDP]] defines a hierarchy of resource types, with a top-level distinction between RDF resources (LDP-RS) and non-RDF resources (LDP-NR). Container (LDPC) is a subtype of RDF resource that may contain other resources as members. There are several subtypes of container, which are primarily differentiated by how much the container-member relationship can be configured. Throughout [[!LDP]] and this specification, these types are important for determining what operations are supported, what header fields are required, and what behavior is expected.

General

LDP Containers (LDPC)

Implementations MUST support the creation and management of [[!LDP]] Basic Containers, and MAY support the creation and management of [[!LDP]] Direct and Indirect Containers.

A server that allows client-managed triples with the ldp:contains predicate MUST be able to keep those client-managed triples separate from server-managed containment triples. If a server cannot keep these two uses of ldp:contains separate then any request to use ldp:contains as the membership predicate ([[!LDP]] 2) for Direct and Indirect Containers, or as a client-managed property, MUST be rejected with a 409 (Conflict) and an accompanying constraints document. Implementations that can distinguish containment triples MAY permit ldp:contains as a membership predicate or client-managed property; such implementations SHOULD support Prefer: header values allowing clients to distinguish this data in the representation of an LDPR as defined in [[!LDP]]: http://www.w3.org/ns/ldp#PreferContainment, http://www.w3.org/ns/ldp#PreferMembership, and http://www.w3.org/ns/ldp#PreferMinimalContainer. ([[!LDP]] 5.4.1.4 expansion)

Non-normative note: [[!LDP]] defines containment relationships as binding an LDPC to LDPRs whose lifecycle it controls and is aware of, and are expressed through containment triples of the form <LDPC-URI> ldp:contains <LDPR-URI>. However, implementations that segregate containment and membership triples — for example, by storing containment relationships in a dedicated named graph — may allow the creation of other triples with the ldp:contains predicate, and thus triples with this predicate do not necessarily imply containment.

LDP Direct Containers

Implementations that support the creation and management of LDP Direct Containers ([[!LDP]] 5.4) use the ldp:membershipResource property to express the membership constant URI (per [[!LDP]] 5.4.1.3), and use either the ldp:hasMemberRelation or ldp:isMemberOfRelation property to express the member relation (per [[!LDP]] 5.4.1.4). These properties are set and updated as follows:

  • Implementations MUST allow the membership constant URI ([[!LDP]] 2) to be set via the ldp:membershipResource property of the content RDF on container creation, or otherwise default to an implementation defined value. Implementations SHOULD use the URI of the newly created LDP Direct Container as the default property value.
  • Implementations MAY allow the membership constant URI to be updated by subsequent PUT or PATCH requests that change the ldp:membershipResource property of the resource content.
  • Implementations MUST allow the membership predicate ([[!LDP]] 2) to be set via either the ldp:hasMemberRelation or ldp:isMemberOfRelation property of the content RDF on container creation, or otherwise default to an implementation defined value. Implementations SHOULD use the default <> ldp:hasMemberRelation ldp:member.
  • Implementations MAY allow the membership predicate to be updated by subsequent PUT or PATCH requests that change either the ldp:hasMemberRelation or ldp:isMemberOfRelation property of the resource content.

LDP Indirect Containers

Each LDP Indirect Container ([[!LDP]] 5.5) is also a conforming LDP Direct Container (per [[!LDP]] 5.5.1.1). Implementations that support the creation and management of LDP Indirect Containers MUST allow control of ldp:membershipResource, ldp:hasMemberRelation, and ldp:isMemberOfRelation properties as descibed for . They also use the ldp:insertedContentRelation property to control the behavior when creating new contained resources (per [[!LDP]] 5.5.2.1). This property is set and updated as follows:

  • Implementations MUST allow the ldp:insertedContentRelation property to be set via the content RDF on container creation, or otherwise default to an implementation defined value. Implementations SHOULD use the default property value ldp:MemberSubject.
  • Implementations MAY allow the ldp:insertedContentRelation property to be updated via the content RDF by subsequent PUT or PATCH requests.

LDP-NR creation

If, in a successful resource creation request, a Link request header with a rel="type" link specifies the LDP-NR interaction model (http://www.w3.org/ns/ldp#NonRDFSource, regardless of Content-Type: value), then the server SHOULD handle subsequent requests to the newly created resource as if it is an LDP-NR. ([[!LDP]] 5.2.3.4 extension)

Constraints Document

When implementation choices result in failure to complete a client request, the response MUST include a Link header with a link relation of http://www.w3.org/ns/ldp#constrainedBy, and a target URI identifying a document expressing the constraints leading to the failure, as outlined by ([[LDP]] 4.2.1.6).

Data Model

Non-normative note: Neither [[LDP]] nor this specification constrains the underlying storage model for RDF data. Each LDP-RS may be entirely independent RDF content, may be a portion of a shared RDF store, or follow some other arrangement.

If a client request cannot be processed because of data model constraints, the response MUST include an appropriate constraints document.

HTTP GET

Additional values for the Prefer header

This specification extends the Prefer header semantics defined in [[!LDP]] 7.2 by describing three additional URIs that may be used in the include and omit parameters of the return=representation preference ([[!RFC7240]] section 4.2). On GET requests:

  • Implementations SHOULD support http://fedora.info/definitions/fcrepo#PreferInboundReferences to request that the response include triples from any LDP-RS housed in that server that feature the requested resource as RDF-object.
  • Implementations MAY support http://www.w3.org/ns/oa#PreferContainedDescriptions to request that the response include representations of any LDPC-contained resources in the response, as defined in [[!annotation-vocab]] section 2.3.17.
  • Implementations MAY support http://fedora.info/definitions/fcrepo#ServerManaged to request that the response omit triples from any LDPR that are managed by the server.

LDP-RSs

Responses to GET requests that apply a Prefer request header to any LDP-RS MUST include the Preference-Applied response header as defined in [[!RFC7240]] section 3 if and only if all specified parameters of the requested preference were applied.

When a GET request is made to an LDP-RS that describes an associated LDP-NR ( and [[!LDP]] 5.2.3.12), the response MUST include a Link header with a rel="describes" link referencing the LDP-NR in question, as defined in [[!RFC6892]].

LDP-NRs

GET requests to any LDP-NR MUST correctly respond to the Want-Digest header defined in [[!RFC3230]].

Non-normative note: In response to requests with a Want-Digest header, the current Digest value should be calculated to enable fixity verification. Otherwise, it is expected that ETag values may be cached. In order to trigger a fresh digest calculation, clients should use the Cache-Control: no-cache header (see [[RFC7234]] section 5.2.1.4) to instruct any intermediate caches or proxies not to return a cached response. See .

HTTP HEAD

The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response, as specified in [[!RFC7231]] section 4.3.2. The server MUST send the same Digest header in the response as it would have sent if the request had been a GET (or omit it if it would have been omitted for a GET). In other cases, the server SHOULD send the same headers in response to a HEAD request as it would have sent if the request had been a GET, except that the payload headers (defined in [[!RFC7231]] section 3.3) MAY be omitted.

HTTP OPTIONS

Any LDPR MUST support OPTIONS per [[!LDP]] 4.2.8.

Non-normative note: Particular Allow: header responses that clients may use to determine implementation support for specific features are described in the appropriate sections of this specification.
Non-normative note: Implementations may support creation and update of an LDP-NR with external content, and this is advertised with the Accept-External-Content-Handling header, see .

HTTP POST

Any LDPC except Version Containers (LDPCv) MUST support POST ([[!LDP]] 4.2.3 / 5.2.3).

Creating LDP-NRs with HTTP POST

Any LDPC except Version Containers (LDPCv) MUST support creation of LDP-NRs on POST ([[!LDP]] 5.2.3.3 MAY becomes MUST). On creation of an LDP-NR, implementations MUST create an associated LDP-RS describing that LDP-NR ([[!LDP]] 5.2.3.12 MAY becomes MUST).

An HTTP POST request that would create an LDP-NR and includes a Digest header (as described in [[!RFC3230]]) for which the instance-digest in that header does not match that of the new LDP-NR MUST be rejected with a 409 (Conflict) response.

An HTTP POST request that includes an unsupported Digest algorithm (as described in [[!RFC3230]]), SHOULD be rejected with a 400 (Bad Request) response.

Non-normative note: Implementations may support creation of LDP-NR using POST with external content, see .

HTTP PUT

Implementations MAY allow the interaction model of an existing resource to be changed by specification of a new LDP type in a rel="type" link in the HTTP Link header. If supported, requests SHOULD be rejected with a 409 (Conflict) response unless the new LDP type specified is a subtype of the resource's current type.

LDP-RSs

Any LDP-RS MUST support PUT to update statements that are not server-managed triples (as defined in [[!LDP]] 2). [[!LDP]] 4.2.4.1 and 4.2.4.3 remain in effect. If an otherwise valid HTTP PUT request is received that attempts to modify resource statements that a server disallows (not ignores per [[!LDP]] 4.2.4.1), the server MUST fail the request by responding with a 4xx range status code, such as 409 (Conflict). The server MUST provide a corresponding response body containing information about which statements could not be persisted. ([[!LDP]] 4.2.4.4 SHOULD becomes MUST). In that response, the restrictions causing such a request to fail MUST be described in a resource indicated by a rel="http://www.w3.org/ns/ldp#constrainedBy" link in the Link response header per [[!LDP]] 4.2.1.6.

LDP-NRs

Any LDP-NR MUST support PUT to replace the binary content of that resource.

An HTTP PUT request that includes a Digest header (as described in [[!RFC3230]]) for which any instance-digest in that header does not match the instance it describes, MUST be rejected with a 409 (Conflict) response.

An HTTP PUT request that includes an unsupported Digest algorithm (as described in [[!RFC3230]]), SHOULD be rejected with a 400 (Bad Request) response.

Non-normative note: Implementations may support creation of LDP-NR using PUT with external content, see .

Creating resources with HTTP PUT

Non-normative note: Implementations may accept HTTP PUT to create resources ([[!LDP]] 4.2.4.6). Behavior regarding containment or non-containment of resources created with HTTP PUT is not defined by [[!LDP]] or this specification.

On creation of an LDP-NR with HTTP PUT, implementations MUST create an associated LDP-RS describing that LDP-NR in the same way that it would when .

Non-normative note: Implementations may support creation of LDP-NR using PUT with external content, see .

HTTP PATCH

Any LDP-RS MUST support PATCH ([[!LDP]] 4.2.7 MAY becomes MUST). [[!sparql11-update]] MUST be an accepted content-type for PATCH. Other content-types (e.g. [[ldpatch]]) MAY be supported.

If an otherwise valid HTTP PATCH request is received that attempts to modify resource statements that a server disallows (not ignores per [[!LDP]] 4.2.4.1), the server MUST fail the request by responding with a 4xx range status code, such as 409 (Conflict). The server MUST provide a corresponding response body containing information about which statements could not be persisted. ([[!LDP]] 4.2.4.4 SHOULD becomes MUST). In that response, the restrictions causing such a request to fail MUST be described in a resource indicated by a rel="http://www.w3.org/ns/ldp#constrainedBy" link in the Link response header per [[!LDP]] 4.2.1.6.

A successful PATCH request MUST respond with a 2xx status code; the specific code in the 2xx range MAY vary according to the response body or request state.

Containment Triples

The server SHOULD NOT allow HTTP PATCH to update an LDPC’s containment triples; if the server receives such a request, it SHOULD respond with a 409 (Conflict) status code.

Interaction models

The server MUST disallow a PATCH request that would change the LDP interaction model of a resource to a type that is not a subtype of the current resource type. That request MUST be rejected with a 409 (Conflict) response.

HTTP DELETE

The DELETE method is optional per [[!LDP]] section 4.2.5 and this specification does not require Fedora servers to implement it. When a Fedora server supports this method, in addition to the requirements imposed on LDPRs within containers outlined in [[!LDP]] section 5.2.5, it must also follow the additional behavior outlined below.

Recursive Delete

Implementations that cannot recurse SHOULD NOT advertise DELETE in response to OPTIONS requests for containers with contained resources.

Non-normative note: Clients should assume from an advertised DELETE that they do not need to look for contained/child resources to clean up.

If a server supports DELETE, any recursion MUST be reckoned along the [[!LDP]] containment relationships linking contained resources.

Implementations MUST NOT return a 200 (OK) or 204 (No Content) response unless the entire operation successfully completed.

Implementations MUST NOT emit a notification that implies the successful DELETE of a resource until the resource has been successfully removed.

Non-normative note: Atomicity is not guaranteed for HTTP DELETE requests that affect multiple resources.

External Binary Content

Non-normative note: External content features expose resources outside of the repository, and careful consideration should be given by implementations to prevent malicious requests from gaining access to sensitive information.
Non-normative note: Variability among client types and locations may mean that LDP-NR content is addressed in ways that are external to the Fedora server but not resolvable by all clients. This specification describes the use of a rel="http://fedora.info/definitions/fcrepo#ExternalContent" link in a Link header to signal, on POST or PUT, that the Fedora server should not consider the request entity to be the LDP-NR's content, but instead that the target of the link gives the URI from which the content might be retrieved. The http(s): [[RFC3986]] and file: [[RFC8089]] URI schemes motivate this specification, but a Fedora server may support other URI schemes for addressing external content per the requirements for advertisement and rejection specified here. The handling attribute is introduced to specify the handling of the external content: either copying, redirecting, or proxying.
Link: <http://example.org/some/content>;
      rel="http://fedora.info/definitions/fcrepo#ExternalContent";
      handling="proxy";
      type="image/tiff"

Fedora servers that do not support the creation of LDP-NRs with content external to the request entity MUST reject such requests with a 4xx range status code, and MUST describe this restriction in a resource indicated by a rel="http://www.w3.org/ns/ldp#constrainedBy" link in the Link response header. Fedora servers MUST reject with a 4xx range status code requests that include multiple rel="http://fedora.info/definitions/fcrepo#ExternalContent" links.

Fedora servers MUST use the handling attribute in the external content link to determine how to process the request. This specification defines the following attibutes and expected behaviors:

Fedora servers MUST reject with a 4xx range status code requests for which the handling attribute is not present or cannot be respected. In the case that the specified handling cannot be respected, the restrictions causing the request to fail MUST be described in a resource indicated by a rel="http://www.w3.org/ns/ldp#constrainedBy" link in the Link response header.

Fedora servers MUST use the value of the type attribute in the external content link as the media type of the external content, if provided. Any Content-Type header in the request SHOULD be ignored. If there is no type attribute:

Implementations receiving requests that would create or update an LDP-NR with content external to the request entity MUST reject the request if they cannot guarantee all of the response headers required by the LDP-NR interaction model in this specification.

Non-normative note: Example headers for a successful response to a HEAD request on external content with handling of redirect (Below, Link headers are written on separate lines for readability, but can also be listed as comma-separated values in a single header per [[RFC8288]] section 3):
Link: <http://www.w3.org/ns/ldp#Resource>;rel="type"
Link: <http://www.w3.org/ns/ldp#NonRDFSource>;rel="type"
Link: <http://host/fcrepo/image/fcr:metadata>; rel="describedby"
Content-Type: application/pdf
Location: http://example.org/document

Advertising External Content Support

In addition to the requirements of , servers supporting external content requests to an LDPR MUST include an Accept-External-Content-Handling header in the response to an OPTIONS request to that resource. The value MUST be a comma separated list of supported behaviors (e.g. Accept-External-Content-Handling: copy,redirect).

External Content for RDF Resources

Non-normative note: This specification takes no position on the use of requests with a rel="http://fedora.info/definitions/fcrepo#ExternalContent" link to create or update LDP-RSs.

Redirected and Proxied External Content

Non-normative note: Fedora servers may support requests with a rel="http://fedora.info/definitions/fcrepo#ExternalContent" link and either of the redirect or proxy preferences. In both of these cases the content remains external to the repository.

GET and HEAD requests to any external LDP-NR MUST correctly respond to the Want-Digest header defined in [[!RFC3230]].

A successful response to a GET and HEAD request for external content with handling of redirect MUST have status code of either 302 (Found) or 307 (Temporary Redirect).

State Tokens

Non-normative note: State tokens are similar to ETags, providing a mechanism for clients to detect changes in resource state without having to compare the entire entity body, and to perform conditional updates. Like ETags, the principle behind state tokens is that implementations have the best information on resource state, and can choose the most accurate and efficient mechanism for clients to detect changes. State tokens differ from ETags in that there is no expectation that the state token must change if the entity body is not byte-for-byte identical, when the underlying state of the resource has not changed. For example, changes in the order of RDF triples, blank node identifiers, and other serialization variations would not require the X-State-Token value to change.
Non-normative note: State tokens can be a more reliable mechanism for detecting changes in resource state than ETags when an implementation cannot provide strong ETags. State tokens can be a more reliable mechanism for detecting changes in resource state than modification dates when the one-second resolution of HTTP date values is not sufficient.

X-State-Token

Implementations MAY include the X-State-Token header field in GET and HEAD responses to provide a token representing the current state of resource. If provided, this value MUST change whenever the underlying state of the resource has changed.

X-If-State-Token

A client MAY include the X-If-State-Token header field in a PATCH or PUT request to make the request conditional on the resource's current state token matching the client's value.

If an implementation does not support state tokens, it MAY ignore any X-If-State-Token header in HTTP PATCH or PUT requests.

An HTTP PATCH or PUT request that includes an X-If-State-Token header MUST be rejected with a 412 (Precondition Failed) response if the implementation supports state tokens, but the client-supplied value does not match the resource's current state token.

Resource Versioning

Implementations MUST provide resource versioning as per Memento [[RFC7089]] with the additional requirements described in this section.

When an LDPR is created with a rel="type" link in the Link header specifying type http://mementoweb.org/ns#OriginalResource to indicate versioning, it MUST be created as an LDPRv and a version container (LDPCv) MUST be created to contain Memento resources (LDPRm) capturing time-varying representations of the LDPRv.

Implementations MAY allow a subsequent PUT request with a rel="type" link in the Link header specifying type http://mementoweb.org/ns#OriginalResource to convert an existing LDPR into an LDPRv. If such a conversion from an LDPR to an LDPRv is supported, it MUST be accompanied by the creation of a version container (LDPCv), as noted above.

Patterns for version creation are described in .

Versioned Resources (LDPRv)

A versioned resource (LDPRv) provides a TimeGate interaction model as detailed in the Memento specification [[RFC7089]]. It otherwise follows the [[!LDP]] specification, the requirements, and the additional behaviors below.

HTTP GET

The Accept-Datetime header is used to request a past state, exactly as per [[!RFC7089]] section 2.1.1. A successful response MUST be a 302 (Found) redirect to the appropriate LDPRm.

If no LDPRm is appropriate to the Accept-Datetime value, implementations SHOULD return a 406 (Unacceptable).

The response to a GET request on an LDPRv MUST include the following headers:

  • A rel="original timegate" link in the Link header referencing itself
  • A <http://mementoweb.org/ns#TimeGate>; rel="type" link in the Link header
  • A <http://mementoweb.org/ns#OriginalResource>; rel="type" link in the Link header
  • At least one rel="timemap" link in the Link header referencing an associated LDPCv
  • A Vary: Accept-Datetime header, exactly as per [[!RFC7089]] section 2.1.2.

It is the presence of these headers that indicates that the resource is versioned.

HTTP PUT

Implementations MUST support PUT, as is the case for any LDPR.

Version Resources (LDPRm)

An LDPRm MAY be deleted; however, it MUST NOT be modified once created.

HTTP GET

Implementations MUST support GET, as is the case for any LDPR. The headers for GET requests and responses on this resource MUST conform to [[!RFC7089]] section 2.1. Particularly it should be noted that the relevant TimeGate for an LDPRm is the original versioned LDPRv. In addition, any response to a GET request MUST include a <http://mementoweb.org/ns#Memento>; rel="type" link in the Link header.

HTTP OPTIONS

Implementations MUST support OPTIONS. A response to an OPTIONS request MUST include Allow: GET, HEAD, OPTIONS as per [[!LDP]]. Implementations MAY include Allow: DELETE if clients can remove a version from the version history, as noted in .

HTTP POST

Implementations MUST NOT support POST for LDPRms.

HTTP PUT

Implementations MUST NOT support PUT for LDPRms.

HTTP PATCH

Implementations MUST NOT support PATCH for LDPRms.

HTTP DELETE

Implementations MAY support DELETE for LDPRms. If DELETE is supported, the server is responsible for all behaviors implied in .

Version Containers (LDPCv)

An LDPCv is both a TimeMap per Memento [[!RFC7089]] and an LDPC. As a TimeMap, an LDPCv MUST conform to Memento [[!RFC7089]].

Implementations MUST NOT allow the creation of an LDPCv that is LDP-contained by its associated LDPRv.

Non-normative note: The application/link-format representation of an LDPCv is not required to include all statements in the LDPCv graph, only those required by TimeMap behaviors.

HTTP GET

Implementations MUST support GET, as is the case for any LDPR. Any response to a GET request MUST include a <http://mementoweb.org/ns#TimeMap>; rel="type" link in the Link header.

An LDPCv MUST respond to GET with an Accept: application/link-format header as indicated in [[!RFC7089]] section 5 and specified in [[!RFC6690]] section 7.3.

Implementations MUST include the Allow header and, if appropriate, the Accept-Post and Accept-Patch headers, and as outlined in .

HTTP OPTIONS

Implementations MUST support OPTIONS. A response to an OPTIONS request MUST include Allow: GET, HEAD, OPTIONS as per [[!LDP]].

The response MAY include Allow: DELETE if the versioning behavior is removable by deleting the LDPCv. See for requirements on DELETE if supported.

The response MAY include Allow: PATCH if the LDPCv has mutable properties. See for requirements on PATCH if supported.

The response MAY include Allow: POST if versions can be explicitly minted by a client. See for requirements on POST if supported.

If an LDPCv supports POST, the response MUST include the Accept-Post header described in [[!LDP]] 7.1.

If an LDPCv supports PATCH, the response MUST include the Accept-Patch header.

HTTP POST

Although an LDPCv is both a TimeMap and an LDPC, implementations MAY disallow POST requests.

Implementations that allow POSTs for LDPCvs

A POST request that does not contain a Memento-Datetime header SHOULD be understood to create a new LDPRm contained by the LDPCv, reflecting the state of the LDPRv at the time of the POST. Any request body MUST be ignored.

A POST request with a Memento-Datetime header SHOULD be understood to create a new LDPRm contained by the LDPCv, with the state given in the request body and the datetime given in the Memento-Datetime request header.

Implementations that disallow POSTs for LDPCvs

If implementations do not support one or both of the POST cases above, they MUST respond to such requests with a 4xx range status code and a link to an appropriate constraints document (see [[!LDP]] 4.2.1.6).

Non-normative note: The constraints document indicated in the rel="http://www.w3.org/ns/ldp#constrainedBy" link in the Link header for an LDPCv POST request should describe a versioning mechanism (e.g. by PUT or PATCH to the LDPRv described by that LDPCv). Disallowing POST suggests that the [[!LDP]] server will manage all LDPRm creation; see Server-Managed Version Creation.

HTTP PUT

Although an LDPCv is both a TimeMap and an LDPC, implementations MAY disallow PUT requests.

HTTP PATCH

Although an LDPCv is both a TimeMap and an LDPC, implementations MAY disallow PATCH requests.

HTTP DELETE

Implementations MAY support DELETE. Implementations that do support DELETE SHOULD do so by both removing the LDPCv and removing the versioning interaction model from the original LDPRv.

Implementation Patterns

Non-normative note: This section describes the way the normative specification might be applied to implement discoverable versioning patterns. If implementations of LDPCv do not support POST to mint versions, that must be advertised via OPTIONS as described in . This allows a client to perform an OPTIONS request on an LDPCv to determine if it can explicitly mint versions. If the LDPCv does not support POST, the client should assume some other mechanism is used to mint versions, for example, the implementation may automatically mint versions instead, but that is outside the requirements of this specification. This document specifies normatively only how LDPCvs and LDPRms can be discovered, and how they should act.

Server-Managed Version Creation

Non-normative note: Upon PUT or PATCH to an LDPRv, a new LDPRm is created in an appropriate LDPCv. This LDPRm is the version of the original LDPRv that was just created.

Client-Managed Version Creation

Non-normative note: An LDPRm for a particular LDPRv is created on POST to any LDPCv associated with that LDPRv. The new LDPRm is contained in the LDPCv to which the POST was made and features in that LDPCv-as-a-TimeMap. This pattern is very flexible and might be useful for migration from other systems into Fedora implementations. Responses from requests to the LDPRv include a rel="timemap" link in the Link header that references the same LDPCv as per [[!RFC7089]] section 5.

Replacing Contents from Mementos

Non-normative note: Using the ingest-by-reference mechanism provided by POST with copy external content handling, as described in , servers may support replacement of the contents of an LDPRv with that of an LDPRm by providing the LDPRm's location as the target of a link indicating an external content request. For example, given an LDPRm with URL http://example.org/some/memento, the appropriate headers would be:
Link: <http://example.org/some/memento>;
      rel="http://fedora.info/definitions/fcrepo#ExternalContent";
      handling="copy";
      type="image/tiff"

Versioning and Containment

Non-normative note: [[!LDP]] is not explicit, but implies that a resource may not be contained by more than one LDPC. Implementations may want to take this implication into account when creating an LDPRm of an LDPC, to avoid having any members of the LDPC be contained by both the LDPRv and the LDPRm of the LDPC. Alternatives include having a LDPRm's containment triple point to the member's LDPRm, or having the LDPRm return triples about the LDPRv, not the LDPRm itself.

Resource Authorization

Implementations MUST follow the recommendations of Web Access Control [[!SOLIDWEBAC]] in configuring access controls.

This section both clarifies (MUST, SHOULD, MAY) requirements where [[!SOLIDWEBAC]] offers open guidance, as well as specifies interactions relative to resources defined by [[!LDP]].

ACLs are LDP RDF Sources

An ACL for a controlled resource on a conforming server MUST itself be an LDP-RS.

ACL Representation and Interpretation

ACL resources are represented as described in [[!SOLIDWEBAC]] Representation Format. Implementations MUST inspect the ACL RDF for authorizations. Authorizations are identified by type definition triples of the form authorization_N rdf:type acl:Authorization, where authorization_N is the URI of an authorization. Implementations MUST use only statements associated with an authorization in the ACL RDF to determine access, except in the case of acl:agentGroup statements where the group listing document is dereferenced. The authorizations MUST be examined to see whether they grant the requested access to the controlled resource. If none of the authorizations grant the requested access then the request MUST be denied.

Non-normative note: Implementations may set default access controls for all resources by including an ACL for the root container with an authorization that applies to access by any agent (acl:agentClass foaf:Agent), applies to any resource (acl:accessToClass ldp:Resource), and is defined to be inherited (acl:default). The example below grants read access (acl:mode acl:Read) but any combination of modes may be specified.

# ACL for https://example.org/root/ in Turtle
@prefix acl: <http://www.w3.org/ns/auth/acl#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix ldp: <http://www.w3.org/ns/ldp#> .

<#authorization_1> a acl:Authorization ;
    acl:agentClass foaf:Agent ;
    acl:accessToClass ldp:Resource ;
    acl:default <https://example.org/root/> ;
    acl:mode acl:Read .

Cross-Domain ACLs

Non-normative note: ACL implementations may require retrieval of one or more ACL resources. Security implications should be considered if remote ACLs are supported.

Implementations MAY restrict support for ACLs to local resources. If an implementation chooses to reject requests concerning remote ACLs, it MUST respond with a 4xx range status code and MUST advertise the restriction with a rel="http://www.w3.org/ns/ldp#constrainedBy" link in the Link response header.

Cross-Domain Group Listings

Non-normative note: [[!SOLIDWEBAC]] groups of agents require retrieval of one or more Group Listing documents. Security implications should be considered if remote Group Listing documents are supported.

Implementations MAY restrict support for [[!SOLIDWEBAC]] groups of agents to local Group Listing documents. If an implementation chooses to reject requests concerning remote Group Listings, it MUST respond with a 4xx range status code and MUST advertise the restriction with a rel="http://www.w3.org/ns/ldp#constrainedBy" link in the Link response header.

Append Mode

The [[!SOLIDWEBAC]] Modes of Access section mentions the acl:mode value acl:Append. In the context of a Fedora implementation, acl:Append should be understood as operations that only append, such as POSTing to a container, or performing a PATCH that only adds triples.

LDP-RS

When a client is allowed to perform acl:Append but not acl:Write operations on an LDP-RS:

  • A DELETE request MUST be denied
  • A PATCH request that deletes triples MUST be denied
  • A PATCH request that only adds triples SHOULD be allowed
  • A PUT request on an existing resource MUST be denied
  • A PUT request to create a new resource MUST be allowed if the implementation supports creating resources using PUT (see: )

LDPC

In addition to requirements in , when a client is allowed to perform acl:Append but not acl:Write operations on an LDPC, a POST request MUST be allowed.

LDP-NR

When a client is allowed to perform acl:Append but not acl:Write operations on an LDP-NR:

  • All DELETE, POST, and PUT requests MUST be denied
  • This specification does not define PATCH behaviors for LDP-NR

Access To Class

Notwithstanding [[!SOLIDWEBAC]]'s lack of support for it, the acl:accessToClass predicate MUST be supported. When an ACL includes an acl:accessToClass statement, it gives access to all resources with the specified type, whether that type is client-managed or server-managed. Implementations MAY use inference to infer types not present in a resource's triples or rel="type" links in the Link header.

Inheritance and Default ACLs

Inheritance of ACLs in Fedora implementations is defined by the [[!SOLIDWEBAC]] ACL Inheritance Algorithm and MUST be reckoned along the [[!LDP]] containment relationships linking controlled resources, with the following modification: In the case that the controlled resource is uncontained and has no ACL, or that there is no ACL at any point in the containment hierarchy of the controlled resource, then the server MUST supply a default ACL. The default ACL resource SHOULD be located in the same server as the controlled resource.

Non-normative note: The predicate acl:default in the [[WEBAC]] vocabulary indicates authorizations that should be inherited. The [[SOLIDWEBAC]] v.0.4.0 documentation is being updated to use this in place of the obsolete predicate acl:defaultForNew.

Notifications

Non-normative note: This section defines when notifications are made available by Fedora implementations, the minimal set of data contained in these notifications, and how the data is serialized. Notifications may be emitted synchronously or asynchronously with the API operations that cause them to be emitted. These notifications are typically used to support external integrations. The structure of these notifications draws upon the existing [[activitystreams-core]] and [[ldn]] specifications. Implementations are free to choose from any transport technology so long as the notifications conform to what is described in the following sections.

Implementers should be aware that some operations may cause multiple resources to change. In these cases, there will be a corresponding notification describing each of the changes. This is especially true for changes to containment or membership triples. This is also true if a DELETE operation triggers changes in any contained resources.

Consumers of these notifications should not expect a strict ordering of the events reported therein: the fact that a notification for Event A is received before a notification for Event B does not imply that Event A occurred before Event B. Implementations may choose to make further guarantees about ordering.

According to the [[activitystreams-core]] specification, it is possible to collect multiple events into a single notification. This specification makes no restriction on the use of activity stream collections.

Notification Events

For every resource whose state is changed as a result of an HTTP operation, there MUST be a corresponding notification made available describing that change.

Notification Serialization

The notification serialization MUST conform to the [[!activitystreams-core]] specification.

Wherever possible, data SHOULD be expressed using the [[!activitystreams-vocabulary]].

Each event described by a notification MUST contain:

Each event described by a notification SHOULD contain:

Notifications SHOULD NOT contain the entire content of repository resources.

Examples

A minimal notification

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "urn:uuid:3c834a8f-5638-4412-aa4b-35ea80416a18",
  "type": "Create",
  "name": "Resource Creation",
  "actor": "http://example.org/agent/fedoraAdmin",
  "object": {
    "id": "http://example.org/fcrepo/rest/resource/path",
    "type": [
      "ldp:Container",
      "ldp:RDFSource"
    ]
  }
}

A basic notification with some additional detail

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    {
      "isPartOf": {
        "@id": "http://purl.org/dc/terms/isPartOf",
        "@type": "@id"
      }
    }
  ],
  "id": "urn:uuid:be29ae69-2134-f1b0-34be-2f91b6d1f029",
  "type": "Update",
  "name": "Resource Modification",
  "published": "2016-07-04T13:46:39Z",
  "inbox": "http://example.org/ldn/inbox/path",
  "actor": [
    {
      "id": "#actor0",
      "type": "Person",
      "name": "fedo raAdmin"
    },
    {
      "id": "#actor1",
      "type": "Service",
      "name": "APIX-core/0.1"
    }
  ],
  "object": {
    "id": "http://example.org/fcrepo/rest/resource/path",
    "updated": "2016-07-04T13:44:39Z",
    "type": [
      "ldp:Container",
      "ldp:RDFSource",
      "http://example.org/type/CustomType"
    ],
    "isPartOf": "http://example.org/fcrepo/rest/"
  }
}

Binary Resource Fixity

Non-normative note: For the purposes of the following specification, a fixity result is an extract or summary of some LDP-NR made according to some explicit procedure. Fixity results are taken for the purpose of comparing different fixity results for the same resource over time, to ensure a continuity of that resource's identity according to the particular procedure used. Examples might include:

This specification describes two fixity verification mechanisms: firstly, as part of content transmission, to guard against faults in transmission, and secondly, by comparison to a known or proffered digest value, to monitor for faults in persistence.

Transmission Fixity

Non-normative note: Transmission fixity may be verified by including a Digest header (defined in [[RFC3230]]) in POST and PUT requests for LDP-NRs.

Persistence Fixity

Non-normative note: A client may retrieve the checksum of an LDP-NR by performing a HEAD or GET request on it with the Want-Digest header (using a HEAD request allows the client to avoid transferring the entire content when only the checksum is needed). The Digest header in the response can be used to infer persistence fixity by comparing it to previously-computed values.

Privacy Considerations

Fedora implementations are subject to the same privacy considerations that are found in the following specifications:

Security Considerations

There are security considerations for any HTTP server exposed to the Internet. Implementations SHOULD make use of the many security-related features of HTTP, including use of the authentication framework defined in the Authentication chapter of the HTTP/1.1 specification [[!RFC7235]].

Fedora implementations are subject to the same security considerations that are found in the following specifications:

Security considerations for features introduced in this specification can be located in their individual sections:

Acknowledgments

The following people have been instrumental in providing thoughts, feedback, reviews, content, criticism and input in the creation of this specification:

Aaron Birkland, Sarven Capadisli, Aaron Coburn, Sergio Fernández, Tom Johnson, Ben Pennell, Nick Ruest, Rob Sanderson, Bethany Seeger, Adam Soroka, Herbert Van de Sompel, Adam Wead, Joshua Westgard, Jared Whiklo, and others in the Fedora Repository, Islandora and Samvera communities.