연결된 웹 스토리지 프로토콜 1.0

W3C 작업 초안

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2026/WD-lws10-core-20260622/
최신 게시 버전:
https://www.w3.org/TR/lws10-core/
최신 편집자 초안:
https://w3c.github.io/lws-protocol/lws10-core/
이력:
https://www.w3.org/standards/history/lws10-core/
커밋 이력
편집자:
Jesse Wright (옥스퍼드 대학교)
Erich Bremer (스토니브룩 대학교)
피드백:
GitHub w3c/lws-protocol (풀 리퀘스트, 새 이슈, 열린 이슈)

초록

Linked Web Storage Protocol 명세는 애플리케이션이 상호 운용 가능한 방식으로 외부에 저장된 데이터에 안전하고 권한이 부여된 접근을 할 수 있도록 하는 것을 목표로 한다.

이 문서의 상태

이 절은 발행 당시 이 문서의 상태를 설명한다. 현재 W3C 발행물과 이 기술 보고서의 최신 개정판 목록은 W3C 표준 및 초안 색인에서 확인할 수 있다.

이는 비공식 제안이다.

이 문서는 Linked Web Storage Working Group에서 권고안 트랙을 사용하여 작업 초안으로 발행했다.

작업 초안으로의 발행은 W3C와 그 회원들의 승인을 의미하지 않는다.

이는 초안 문서이며 언제든지 다른 문서로 갱신, 대체 또는 폐기될 수 있다. 이 문서를 진행 중인 작업이 아닌 다른 것으로 인용하는 것은 적절하지 않다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성했다. W3C는 이 그룹의 산출물과 관련하여 이루어진 특허 공개의 공개 목록을 유지하며, 해당 페이지에는 특허 공개 지침도 포함되어 있다. 개인이 필수 청구항을 포함한다고 믿는 특허를 실제로 알고 있는 경우, 그 개인은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 한다.

이 문서는 2025년 8월 18일 W3C 프로세스 문서의 적용을 받는다.

1. 문서 규약

이 절은 비규범적이다.

2. 소개

2.1 리소스 접근

LWS 프로토콜은 어떤 주체가 일부 리소스를 일부 에이전트에게 제공할 수 있도록 하는 표준 상호작용을 정의한다.

2.2 보안과 개인정보 보호

리소스 관리자제공되는 리소스를 비공개로 유지할 수 있고, 누구나 공개적으로 사용할 수 있게 할 수도 있으며, 그 가시성을 제한된 집합의 요청 에이전트로 제한할 수도 있다.

2.3 적합성

비규범적이라고 표시된 절뿐 아니라, 이 명세의 모든 작성 지침, 다이어그램, 예시 및 참고는 비규범적이다. 이 명세의 그 밖의 모든 내용은 규범적이다.

이 문서의 핵심어 MAY, MUST, MUST NOT, OPTIONAL, RECOMMENDED, REQUIRED, SHOULD, 및 SHOULD NOT은 여기 표시된 것처럼 모두 대문자로 나타나는 경우에, 그리고 그 경우에만, BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석된다.

LWS 서버는 이 명세의 관련 "MUST" 문을 모두 준수하는 HTTP 서버 [rfc9112]이다. 구체적으로, 이 문서의 9. 작업에 있는 관련 규범적 "MUST" 문을 준수해야 한다.

LWS 클라이언트는 이 명세의 관련 "MUST" 문을 모두 준수하는 HTTP 클라이언트 [rfc9112]이다. 구체적으로, 이 문서의 9. 작업에 있는 관련 규범적 "MUST" 문을 준수해야 한다.

3. 용어

"authorization server" 및 "client"라는 용어는 OAuth 2.0 Authorization Framework [RFC6749]에서 정의된다.

"end-user" 및 "issuer"라는 용어는 OpenID Connect Core 1.0 [OPENID-CONNECT-CORE]에서 정의된다.

이 명세는 다음 용어를 정의한다:

(위험 기능) 이슈: 절이 제거될 수 있음

이 명세는 제공되는 리소스에 대한 작업, 그 결과로 생기는 상태 변화, 그리고 요청 에이전트에게 요청된 정보를 제공하거나 작업의 결과를 알리기 위한 응답을 정의한다. 작업제공되는 리소스에 대해 수행할 수 있는 다음 동작 중 하나이다:

  • 리소스 생성 -
  • 리소스 읽기 -
  • 리소스 갱신 -
  • 리소스 삭제 -

다음 절에서는 이러한 작업의 의미론과 응답을 설명하지만, 다음 핵심 응답은 모든 작업에 적용된다:

  • 성공 - 작업이 완료된 것으로 여겨진다. 이는 제공되는 리소스의 내용을 전달하는 리소스 표현을 동반할 수 있다. 성공 응답은 리소스 생성 작업에 대해서는 정의되지 않는다. 대신 created를 참조하라.
  • 허용되지 않음
  • 알 수 없는 요청자
  • 알 수 없는 오류 - 명세에서 예상하지 못한 오류 조건이 발생하는 경우를 위해 예약됨

4. 인증

이 절은 linked web storage 서버와 상호작용하는 에이전트와 최종 사용자를 식별하기 위한 메커니즘을 정의한다. 이 명세는 인증 자격 증명의 특정 형식을 의무화하지는 않지만, 기존 신원 시스템을 linked web storage 권한 부여 프레임워크와 함께 사용할 수 있는 방법을 설명한다.

4.1 인증 자격 증명 데이터 모델

이 절에서 설명하는 데이터 모델은 인증 자격 증명의 모든 구체적인 직렬화에 대한 요구사항을 개괄한다.

인증 자격 증명은 주체에 관한 변조 증거가 있는 클레임을 포함해야 하며, 여기에는 다음이 포함된다:

4.2 인증 자격 증명 검증

인증 자격 증명의 검증에는 자격 증명의 검증자와 발급자 사이의 신뢰 관계가 필요하다. 이 신뢰 관계는 MAY 대역 외 메커니즘을 통해 수립될 수 있다. 검증자와 발급자 사이의 신뢰를 수립하기 위한 추가 메커니즘은 특정 인증 스위트에 개괄된다.

인증 자격 증명MUST 서명되어야 한다. 그 서명에 비대칭 암호화를 사용하는 것이 RECOMMENDED된다.

4.3 인증 자격 증명 유형 식별자

인증 스위트는 토큰 유형 URI와 연관되어야 한다. 인증 스위트는 IANA "OAuth URI" 레지스트리에 정의된 URI를 사용하는 것이 SHOULD된다.

5. 권한 부여

Linked Web Storage는 웹에서 보호된 데이터를 지속적으로 저장하고 관리하기 위한 메커니즘을 설명한다. 권한 부여는 에이전트가 이 보호된 데이터에 접근하기 위해 접근 토큰을 요청하고 제시하는 메커니즘이다.

이 절은 OAuth 2.0 [RFC6749]을 접근 토큰을 획득하고 제시하기 위한 기준 메커니즘으로 삼는 권한 부여 프레임워크를 정의한다. 서버는 이 기준을 넘어서는 추가 권한 부여 메커니즘을 지원할 MAY 있다.

5.1 역할

LWS 권한 부여의 역할은 OAuth 2.0 제1.1절 [RFC6749]에서 정의한 것과 동일하다: 리소스 소유자, 리소스 서버, 클라이언트(이 명세에서는 모호성을 피하기 위해 권한 부여 클라이언트라고 부름), 그리고 권한 부여 서버. 스토리지 서버는 LWS 스토리지 명세도 준수하는 리소스 서버의 한 유형이다.

5.2 프로토콜 흐름

이 명세는 클라이언트와 권한 부여 서버 사이의 상호작용뿐 아니라 클라이언트와 준수하는 스토리지 서버 사이의 상호작용을 설명한다.

권한 부여 서버와 스토리지 서버 사이의 상호작용은 이 명세의 범위를 벗어난다. 권한 부여 서버는 스토리지 서버와 동일한 서버일 수도 있고 별도의 엔터티일 수도 있다.

5.2.1 권한 부여 서버 발견

스토리지 서버가 관리하는 모든 보호된 리소스에는 신뢰할 수 있는 권한 부여 서버가 생성한 유효한 접근 토큰이 필요하다. 클라이언트는 보호된 리소스에 승인되지 않은 HTTP 요청을 함으로써 신뢰할 수 있는 권한 부여 서버의 위치를 발견할 수 있다.

401 (Unauthorized) 응답을 생성하는 스토리지 서버는 적어도 하나의 준수하는 챌린지를 포함하는 WWW-Authenticate 헤더 필드를 전송해야 한다. 준수하는 챌린지는 아래에 설명된 매개변수를 포함한다:

  • as_uri REQUIRED — 이 매개변수의 값은 클라이언트가 접근 토큰을 검색할 수 있는 권한 부여 서버를 식별하는 URI이다. 이 매개변수의 값은 유효한 접근 토큰의 iss 클레임과 동일하다.
  • realm REQUIRED — 이 매개변수의 값은 보호 범위를 나타내는 URI이다. 이 값은 접근 토큰의 audience (aud) 클레임에 포함된다. 클라이언트는 MUST 원래 요청의 URI가 이 응답에 제시된 realm 안에 논리적으로 포함되는지 검증해야 한다.

다른 헤더와 매개변수가 포함될 MAY 있다.

401 응답 예시는 아래에 포함되어 있다.

HTTP/2 401 Unauthorized
Link: <https://storage.example/storage_1/metadata>; rel="storageDescription"
WWW-Authenticate: Bearer as_uri="https://authorization.example",
                realm="https://storage.example/storage_1",
                error="invalid_token"

5.2.2 권한 부여 서버 메타데이터

권한 부여 서버는 [RFC8414]에 설명된 대로 클라이언트가 엔드포인트 위치와 기능을 발견할 수 있도록 메타데이터 리소스를 제공해야 한다. 이 메타데이터 리소스는 /.well-known/lws-configuration 경로의 URL에서 사용할 수 있어야 한다.

권한 부여 서버는 서버 메타데이터 문서에 subject_token_types_supported 항목을 포함하여 자신이 지원하는 subject token을 알리는 것이 SHOULD된다. 이 항목은 권한 부여 서버의 토큰 엔드포인트에 제공할 수 있는 유효한 subject_token_type 값 목록을 포함하는 JSON 배열이다.

권한 부여 서버 메타데이터 리소스의 예시는 아래에 포함되어 있다.

{
    "issuer": "https://authorization.example",
    "grant_types_supported": [
        "urn:ietf:params:oauth:grant-type:token-exchange"],
    "token_endpoint": "https://authorization.example/token",
    "jwks_uri": "https://authorization.example/jwks",
    "claims_supported": [
        "sub",
        "iss",
        "client_id",
        "aud"],
    "response_types_supported": [
        "token"],
    "subject_token_types_supported": [
        "urn:ietf:params:oauth:token-type:jwt",
        "urn:ietf:params:oauth:token-type:id-token"]
}

5.2.3 토큰 교환

LWS 권한 부여 서버는 준수하는 OAuth 2.0 권한 부여 서버로서, 스토리지 서버와 함께 사용할 접근 토큰을 클라이언트에 발급할 수 있다. 접근 토큰을 발급하려면, 클라이언트는 먼저 인증 자격 증명과 같은 유효한 subject token을 OAuth 2.0 Token Exchange [RFC8693]를 통해 권한 부여 서버에 제시해야 한다.

5.2.3.1 요청

권한 부여 서버의 토큰 엔드포인트는 OAuth 2.0 Token Exchange [RFC8693]에 설명된 대로 urn:ietf:params:oauth:grant-type:token-exchange grant type을 지원해야 한다.

token exchange grant type을 수행할 때 다음 추가 요구사항이 적용된다:

  • resource 매개변수는 REQUIRED이다. 이 매개변수의 값은 URI여야 하며, 결과 접근 토큰의 aud (audience) 클레임을 채우는 데 사용된다. 제공된 값은 WWW-Authenticate 챌린지의 realm 매개변수 응답과 동일하다. 권한 부여 서버는 resource 매개변수가 알 수 없거나 신뢰할 수 없는 스토리지를 식별하는 모든 요청을 거부해야 한다.
  • subject_token 매개변수는 REQUIRED이다. 이 매개변수의 값은 인증 자격 증명과 같은 유효한 subject token을 포함해야 한다.
  • 클라이언트에 접근 토큰을 반환하기 전에, 권한 부여 서버는 제시된 모든 토큰을 성공적으로 검증해야 한다.

토큰 요청의 비규범적 예시(subject_token 매개변수는 잘림).

POST /token HTTP/1.1
Host: authorization.example
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange
&resource=https%3A%2F%2Fstorage.example%2Fstorage_1
&subject_token=eyJ0eXAiOiJhcytqd3QiLCJhbGciO...fiK51VwhsxJ-siBMR-YFiA
&subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aid_token
5.2.3.2 응답

토큰 요청이 유효하고 클라이언트가 요청을 할 권한이 있는 경우, 권한 부여 서버 응답은 OAuth 2.0 Authorization Framework [RFC6749]의 제5.1절을 준수해야 한다. 결과 접근 토큰은 JSON Web Token Profile for OAuth 2.0 Access Tokens [RFC9068]를 준수해야 한다.

또한, 접근 토큰은 다음 요구사항을 충족해야 한다:

  • sub (subject) — REQUIRED. 이 클레임은 작업을 수행하는 에이전트를 식별하는 URI여야 한다.
  • iss (issuer) — REQUIRED. 이 클레임은 권한 부여 서버의 URI여야 한다.
  • client_id (client id) — REQUIRED. 이 클레임은 클라이언트를 식별하는 URI여야 한다.
  • aud (audience) — REQUIRED. 이 클레임은 클라이언트가 resource 매개변수에 제공한 URI를 포함해야 한다. 이 값은 접근 토큰이 유효한 엔터티를 제한하는 데 사용된다. 이는 스토리지 서버가 WWW-Authenticate 챌린지의 realm 매개변수에서 제공한 값과 동일하다.
  • exp (expiration) — REQUIRED. 권한 부여 서버는 토큰 도난으로 인한 노출을 제한하기 위해 짧은 수명의 토큰을 발급하는 것이 SHOULD된다 (RECOMMENDED: 300초 이하).
  • iat (issued at) — REQUIRED.
  • jti (JWT ID) — REQUIRED.

성공적인 토큰 응답의 비규범적 예시는 아래에 포함되어 있다.

HTTP/1.1 200 OK
Content-Type: application/json

{
    "access_token":"eyJ0eXAiOiJhcytqd3QiLCJhbGciOiJFUzI1NiIs...DeWt4QuZXso",
    "token_type":"Bearer",
    "expires_in":3600
}

유효하지 않거나 승인되지 않은 모든 요청은 OAuth 2.0 Authorization Framework [RFC6749]의 제5.2절에 설명된 대로 오류 응답을 발생시켜야 한다.

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
    "error":"invalid_request"
}
5.2.3.3 접근 토큰 예시

이 절은 비규범적이다.

권한 부여 서버가 발급한 접근 토큰의 예시는 아래에 포함되어 있다.

{
  "kid": "ec51c6b2",
  "kty": "EC",
  "alg": "ES256",
  "crv": "P-256",
  "typ": "at+jwt"
}
.
{
  "sub": "https://id.example/agent",
  "iss": "https://authorization.example",
  "client_id": "https://app.example/id",
  "aud": "https://storage.example",
  "exp": 1735686300,
  "iat": 1735686000,
  "jti": "550e8400-e29b-41d4-a716-446655440000"
}
.
signature

5.2.4 스토리지 서버에 의한 토큰 검증

클라이언트가 접근 토큰을 보유하게 되면, 이 토큰을 스토리지 서버에 제시한다. 스토리지 서버는 어떤 작업을 수행하기 전에 이 토큰을 검증할 책임이 있다.

5.2.4.1 제시

클라이언트는 [RFC6750]에 정의된 인증 스킴과 함께 Authorization 헤더를 사용하여 스토리지 서버에 접근 토큰을 제시해야 한다.

Authorization: Bearer eyJ0eXAiOiJhcytqd3QiLCJhbGciOiJFUzI1NiIs...DeWt4QuZXso
5.2.4.2 검증

스토리지 서버는 다음 검사를 수행하여 접근 토큰을 검증해야 하며, 실패가 하나라도 있으면 요청을 거부해야 한다:

  • JWT 서명 검증: 권한 부여 서버 메타데이터에 지정된 jwks_uri에서 검색한 권한 부여 서버의 공개 키를 사용하여 JWT 서명을 검증한다. 스토리지 서버는 이러한 키를 캐시하는 것이 SHOULD되며, 키 교체를 지원해야 한다.
  • 발급자 검증: iss 클레임이 예상되는 권한 부여 서버 식별자와 일치하는지 검증한다.
  • Audience 검증: aud 클레임이 정확히 하나의 값을 포함하고, 이 값이 대상 리소스를 논리적으로 포함하는 스토리지 서버를 식별하는 URI인지 검증한다.
  • 시스템 간 허용 가능한 시계 오차를 고려한 시간 검증.
    • 현재 시간이 exp (expiration) 클레임보다 이전인지 검증한다.
    • nbf (not before) 클레임이 있는 경우, 현재 시간이 그보다 이전이 아닌지 검증한다.
    • iat (issued at) 클레임이 미래가 아닌지 검증한다.

검증이 실패하면, 스토리지 서버는 적절한 오류 매개변수(예: invalid_token, invalid_request 또는 insufficient_scope)를 포함하는 WWW-Authenticate 헤더와 함께 401 Unauthorized를 반환해야 한다.

토큰이 그 밖의 면에서는 유효하지만 권한 부여 정책이 요청된 작업을 허용하지 않는 경우, 스토리지 서버는 요청을 거부해야 한다.

6. 발견

6.1 스토리지 설명 리소스

스토리지 설명 리소스는 클라이언트가 스토리지와 상호작용할 때 사용할 수 있는 정보를 제공하며, 여기에는 기능 및 서비스 엔드포인트에 대한 설명이 포함된다.

6.1.1 데이터 모델

  • id - id 속성은 REQUIRED이다. 그 값은 스토리지를 식별하는 URI여야 한다.
  • type - type 속성은 REQUIRED이다. 그 값은 Storage와 같은 문자열이거나 Storage와 같은 항목을 포함하는 문자열 집합이어야 한다 (대소문자 구분).
  • capability - capability 속성은 OPTIONAL이다. 그 값은 기능의 집합이어야 하며, 각 기능은 다음 속성을 포함하는 맵으로 설명된다. 추가 속성이 존재할 MAY 있다.
    • id - id 속성은 OPTIONAL이다. 존재하는 경우, 그 값은 URI여야 한다.
    • type - type 속성은 REQUIRED이다. 그 값은 문자열 또는 문자열 집합이어야 한다.
  • service - service 속성은 REQUIRED이다. 그 값은 서비스의 집합이어야 하며, 각 서비스는 다음 속성을 포함하는 맵으로 설명된다. 추가 속성이 존재할 MAY 있다.
    • id - id 속성은 OPTIONAL이다. 존재하는 경우, 그 값은 URI여야 한다.
    • type - type 속성은 REQUIRED이다. 그 값은 문자열 또는 문자열 집합이어야 한다.
    • serviceEndpoint - serviceEndpoint 속성은 REQUIRED이다. 그 값은 URI여야 한다.
8: 최소 스토리지 설명 리소스
{
  "@context": "https://www.w3.org/ns/lws/v1",
  "id": "https://storage.example/",
  "type": "Storage",
  "service": [{
    "type": "StorageDescription",
    "serviceEndpoint": "https://storage.example/description"
  }]
}

6.1.2 발견과 바인딩

스토리지 리소스를 대상으로 하는 모든 GETHEAD 요청에 대한 응답은 대상이 스토리지 설명 리소스의 URI인 Link 헤더를 포함해야 하며, 그 값이 https://www.w3.org/ns/lws#storageDescription와 같은 관계 (rel) 매개변수를 포함해야 한다.

역참조될 때, 스토리지 설명스토리지를 식별하는 id 속성을 포함해야 한다. 또한 service 속성은 그 type이 StorageDescription과 같고 serviceEndpoint스토리지 설명의 URL과 같은 서비스 설명을 포함해야 한다.

참고

스토리지 설명의 URI는 스토리지를 식별하는 URI와 다를 수 있으며, 이는 다시 스토리지 루트와 다를 수 있다. 결과 표현이 이 문서에 개괄된 요구사항을 준수하는 한, 이러한 URI는 동일할 수도 있다.

6.1.3 스토리지 기능

스토리지 설명스토리지가 지원하는 추가 기능에 대한 설명을 포함할 수 있다.

6.1.4 스토리지 서비스

StorageDescription 서비스 외에도, 스토리지 설명 리소스스토리지에 연결된 다른 서비스에 대한 링크를 포함할 수 있다. 이러한 서비스의 API 정의는 이 명세의 범위를 벗어난다.

6.1.5 스토리지 설명 표현

스토리지 설명 리소스는 미디어 유형 application/lws+json으로 직렬화 가능해야 한다. 다른 표현은 콘텐츠 협상을 통해 사용 가능할 MAY 있다.

9: 스토리지 설명 리소스
{
  "@context": "https://www.w3.org/ns/lws/v1",
  "id": "https://storage.example/",
  "type": "Storage",
  "capability": [{
    "type": "https://feature.example/PatchSupport",
    "mediaType": {
      "text/turtle": ["application/sparql-update"],
      "application/n-triples": ["application/sparql-update"],
      "application/linkset+json": ["application/merge-patch+json", "application/json-patch+json"]
    }
  }, {
    "type": "https://feature.example/ResumableUploads"
  }, {
    "type": "https://feature.example/ContentNegotiation",
    "source": "application/ld+json",
    "target": ["text/turtle", "application/n-triples"]
  }, {
    "type": "https://feature.example/ContentNegotiation",
    "source": "image/jpeg",
    "target": ["image/png"]
  }],
  "service": [{
    "type": "NotificationService",
    "serviceEndpoint": "https://storage.example/notification/api",
    "subscriptionType": ["WebhookSubscription"]
  }, {
    "type": "TypeIndexService",
    "serviceEndpoint": "https://storage.example/types/index"
  }, {
    "type": "TypeSearchService",
    "serviceEndpoint": "https://storage.example/types/search"
  }, {
    "type": "DataSharingService",
    "serviceEndpoint": "https://storage.example/sharing/api"
  }, {
    "type": "StorageDescription",
    "serviceEndpoint": "https://storage.example/description"
  }]
}

7. 논리적 리소스 구성

7.1 컨테이너 모델

Linked Web Storage는 리소스를 컨테이너로 구성한다. 컨테이너는 그 구성원이라고 불리는 다른 리소스에 대한 참조를 보유하는 특수화된 리소스이다. 컨테이너는 디렉터리 또는 컬렉션과 유사한 조직 단위 역할을 하며, 클라이언트가 리소스를 그룹화, 발견, 탐색할 수 있게 한다. 컨테이너는 구성원 리소스에 대한 참조를 유지하며, 이는 컨테이너가 아닌 리소스와 추가 컨테이너 리소스를 모두 포함할 수 있어 계층적 형성을 가능하게 한다. 일반적으로 컨테이너는 구성원에 대한 메타데이터나 열거 외에는 최소한의 고유 콘텐츠만 보유하며, 그 주요 역할은 하위 리소스를 집계하고 구조화하는 것이다. 스토리지 시스템의 루트는 컨테이너로 지정되며, 상위 부모가 없는 최상위 조직 단위 역할을 한다. 컨테이너는 'ContainerPage' 유형을 사용하여 구성원 목록에 대한 페이지네이션을 지원해야 하며, 'first', 'next', 'prev', 'last'와 같은 속성을 가진다. 표현은 특정 프레임과 규범적 컨텍스트를 가진 JSON-LD를 사용해야 하며, 선택적으로 'Vary: Accept' 헤더를 통해 콘텐츠 협상을 알릴 수 있다. 스토리지는 루트 컨테이너로 기능하여 직접 쓰기를 가능하게 할 MAY 있다.

모든 LWS 스토리지에는 최상위 조직 단위 역할을 하는 스토리지 루트가 있다. 스토리지 루트는 부모가 없으며 스토리지 계층의 진입점 역할을 한다.

LWS의 리소스는 다음 중 하나로 분류된다:

7.2 포함 관계

리소스와 그 부모 컨테이너 사이의 포함 관계rel="up" 링크 관계를 통해 표현된다. 서버는 루트가 아닌 모든 리소스에 대한 GET 및 HEAD 요청의 응답에서 부모 컨테이너를 가리키는 rel="up"이 있는 Link 헤더를 포함해야 한다.

Link: </alice/notes/>; rel="up"

컨테이너의 구성원은 그 표현에서 items 속성을 사용하여 나열된다. 서버가 이 목록을 관리하며, 클라이언트는 이를 직접 수정할 수 없다. 구성원 변경은 리소스 생성 및 삭제의 부수 효과로 발생한다.

7.3 포함 관계 무결성

서버는 항상 포함 관계 무결성을 유지해야 한다:

7.4 리소스 식별

리소스는 URI로 식별된다. 리소스의 URI는 포함 관계 계층에서의 위치와 독립적이다. 서버는 리소스 생성 중 URI를 할당하고, 클라이언트 힌트(예: Slug 헤더)를 포함할 MAY 있지만, 클라이언트는 URI 구조가 포함 관계를 반영한다고 가정해서는 안 된다.

포함 관계는 URI 경로 구조가 아니라 메타데이터(rel="up" 링크 및 컨테이너 표현의 items 속성)를 통해 표현된다. 이러한 분리는 서버가 명확히 정의된 조직 모델을 유지하면서도 URI 할당에서 유연성을 가질 수 있게 한다.

7.5 컨테이너 구성원 관계와 권한 부여

클라이언트가 컨테이너에 대한 읽기 접근 권한을 가진 경우, 컨테이너 표현은 해당 클라이언트가 접근할 수 있는, 그 컨테이너 안에 포함된 모든 리소스의 식별자를 포함해야 한다. 또한 클라이언트가 접근할 수 없는, 그 컨테이너 안에 포함된 리소스의 식별자도 포함할 MAY 있다.

클라이언트가 컨테이너 목록을 읽을 수 있다는 것은 포함된 리소스 자체에 접근할 수 있음을 의미하지 않으며, 그 반대도 마찬가지이다.

8. 컨테이너

8.1 컨테이너 표현

클라이언트가 컨테이너를 검색하면, 서버는 그 컨테이너와 그 내용을 설명하는 구조화된 컨테이너 표현을 반환한다. 이 절은 컨테이너 표현의 필수 및 선택 속성을 정의한다.

8.1.1 컨테이너 속성

컨테이너 표현은 다음 속성을 포함해야 한다:

  • id: 컨테이너의 URI.
  • type: 값 "Container".
  • totalItems: 클라이언트에게 공개될 수 있는, 컨테이너에 포함된 리소스의 총 개수를 나타내는 정수. 이 개수는 정확한 것이 SHOULD되지만 근사치일 MAY 있다.
  • items: 포함된 리소스 설명의 배열(아래 참조). 컨테이너가 비어 있는 경우, 이는 빈 배열이어야 한다. 컨테이너 목록이 페이지네이션되는 경우, items는 현재 페이지의 리소스만 포함한다. 자세한 내용은 페이지네이션을 참조하라.

8.1.2 포함된 리소스 설명

items 배열의 각 항목은 컨테이너 안에 포함된 리소스를 설명한다. 포함된 리소스 설명은 다음을 포함해야 한다:

  • id: 포함된 리소스의 URI.
  • type: 리소스의 유형. "DataResource" 또는 "Container"이거나, 이 두 문자열 중 적어도 하나를 포함하는 배열이어야 한다. 서버는 추가 사용자 정의 유형을 URI로 포함할 MAY 있다 (예: ["DataResource", "http://example.org/customType"]).

포함된 리소스 설명은 다음을 포함하는 것이 SHOULD된다:

  • mediaType: 리소스의 미디어 유형(예: "text/plain", "image/jpeg"). DataResources의 경우 존재해야 한다.
  • size: 정수로 표현된 리소스의 바이트 단위 크기.
  • modified: ISO 8601 date-time 문자열로 표현된, 리소스가 마지막으로 수정된 날짜와 시간.

8.1.3 컨테이너 표현 예시

다음 예시는 두 개의 리소스를 포함하는 /alice/notes/컨테이너를 보여준다:

{
  "@context": "https://www.w3.org/ns/lws/v1",
  "id": "/alice/notes/",
  "type": "Container",
  "totalItems": 2,
  "items": [
    {
      "type": "DataResource",
      "id": "/alice/notes/shoppinglist.txt",
      "mediaType": "text/plain",
      "size": 47,
      "modified": "2025-11-24T12:00:00Z"
    },
    {
      "type": ["DataResource", "http://example.org/customType"],
      "id": "/alice/notes/todo.json",
      "mediaType": "application/json",
      "size": 2048,
      "modified": "2025-11-24T13:00:00Z"
    }
  ]
}

9. 작업

이 절은 Linked Web Storage (LWS) 서버가 지원해야 하는 네 가지 핵심 작업을 정의한다. 이러한 작업은 리소스와 컨테이너를 전송 방식에 독립적인 방식으로 조작하며, 구현 세부사항보다 의미론에 초점을 둔다. 각 작업은 입력, 예상 동작 및 가능한 응답을 지정한다. 응답에는 성공 표시자, 리소스 표현(해당되는 경우) 및 오류 조건이 포함된다. 구현은 이러한 작업을 원자적이고 일관되게 처리해야 하며, 이는 각 작업이 완전히 성공하거나 부분적인 부수 효과 없이 실패해야 함을 의미한다. 오류가 발생한 경우, 응답은 민감한 정보를 누출하지 않으면서 에이전트가 문제를 이해할 수 있을 만큼 충분한 세부 정보를 제공하는 것이 SHOULD된다.

각 핵심 작업(create, read, update, delete)에 대해 사용할 HTTP 메서드, 필요한 헤더 또는 특별한 고려사항(ETags를 통한 동시성 제어, 콘텐츠 협상 및 컨테이너 목록에 대한 페이지네이션 포함), 그리고 서버가 수행하고 반환해야 하는 것을 설명한다. 표준 HTTP 상태 코드는 결과를 나타내는 데 사용되며, 할당량 초과(507 Insufficient Storage) 또는 사전 조건 실패(412 Precondition Failed)와 같은 시나리오에 대한 추가 매핑을 포함한다. 이 바인딩은 HTTP/1.1 및 관련 RFC(예: HTTP 의미론을 위한 [RFC7231], 범위 요청을 위한 [RFC7233], PATCH를 위한 [RFC5789], Web Linking을 위한 [RFC8288], 그리고 Link Sets를 위한 [RFC9264])를 따르려 하므로, 웹 표준과 자연스럽게 통합된다. 발견 가능성은 Link 헤더 및 401 응답의 WWW-Authenticate 헤더와 같은 메커니즘을 통해 강조되어, 하드코딩된 URI 위치를 피한다. 메타데이터 통합은 작업 전반에서 필요하며, 서버 관리 속성과 사용자 관리 속성을 위해 Link Sets의 원자성과 사용을 보장한다.

참고: 이 명세의 모든 예시와 마찬가지로, 이 절에 제시된 예시(HTTP 요청 및 응답 스니펫)는 일반적인 사용 방식을 설명하기 위한 비규범적 내용이다. 실제 요구사항은 설명 텍스트와 표에 명시되어 있다. 또한 이 바인딩은 HTTP(초기 대상 프로토콜)를 다루지만, LWS 작업은 원칙적으로 향후 다른 프로토콜에 바인딩될 수 있다. 서버는 컨테이너 표현에 대해 application/lws+json, application/ld+json, 및 application/json의 콘텐츠 협상을 지원해야 한다 (11. LWS 미디어 유형 참조). 서버는 Turtle과 같은 형식을 추가로 지원할 MAY 있다.

9.1 메타데이터

이 절은 LWS 리소스와 메타데이터를 연결하기 위한 모델을 정의한다. LWS 메타데이터 시스템은 Web Linking [RFC8288]의 원칙을 기반으로 하며, 이를 통해 서버는 형식화된 링크를 사용하여 리소스 간 관계를 설명할 수 있다. 메타데이터는 발견 가능성을 높이고, 자기 설명적 API를 지원하며, 리소스 작업 및 컨테이너 계층과 정렬된다.

메타데이터 모델 LWS의 모든 메타데이터는 리소스(링크 컨텍스트)에서 시작되는 형식화된 링크의 집합으로 표현된다. 각 링크는 다음으로 구성된다:

메타데이터는 리소스와 그 표현을 구별하여, 해당되는 경우 여러 미디어 유형을 허용한다. 데이터 리소스의 경우, 메타데이터에는 표현이 포함되며, 각 표현은 mediaType 및 선택적 sizeInBytes를 가진다. 컨테이너데이터 리소스의 경우, 그 부모 컨테이너 리소스에 대한 링크를 해당 리소스의 메타데이터 일부로 간주한다.

Linkset 리소스 스토리지의 각 리소스에 대해, 서버는 [RFC9264]에 따라 메타데이터 링크를 독립형 리소스로 사용할 수 있게 해야 한다.

메타데이터 발견 클라이언트는 주로 GET 또는 HEAD 요청에 대한 응답의 Link 헤더를 통해 메타데이터를 발견한다.

메타데이터 유형

범주 설명
시스템 관리 서버가 유지 관리하며 읽기 전용이다. linkset, type, mediaType, size, modified를 포함한다.
핵심 메타데이터 클라이언트가 관리한다(서버 제한의 적용을 받음). up, items, title, creator를 포함한다.
사용자 정의 사용자가 생성한 사용자 지정 어휘 및 색인.

수정 가능성 고려사항 핵심 메타데이터는 클라이언트가 수정할 MAY 있다. 상호 운용성을 보장하기 위해, 서버는 자신의 기능을 알리기 위해 표준 HTTP 헤더를 사용해야 한다:

  1. 메서드 발견: 서버는 Allow 헤더를 통해 linkset 리소스에 대한 GET 및 PATCH 작업 지원을 알려야 한다.

  2. 패치 형식 발견: 서버는 Accept-Patch 헤더를 통해 JSON Merge Patch [RFC7386] 지원을 알려야 한다: Accept-Patch: application/merge-patch+json.

  3. 선택적 메서드: 서버는 PUT 또는 대체 패치 형식을 지원할 MAY 있으며, 지원하는 경우 각각 Allow 및 Accept-Patch 헤더에 포함되어야 한다.

[!IMPORTANT] 클라이언트는 리소스 헤더에 광고되지 않은 한 PUT 또는 특정 패치 형식 지원을 가정해서는 안 되며, 405 Method Not Allowed 또는 415 Unsupported Media Type 응답을 우아하게 처리해야 한다.

메타데이터 관리 메타데이터는 리소스와 연결된 linkset 리소스 URI와 상호작용하여 관리된다. 서버는 갱신에 대한 동시성 제어를 지원해야 한다.

9.2 리소스 생성

리소스 생성 작업은 새 제공되는 리소스를 기존 컨테이너에 추가한다. 이 작업은 데이터 리소스와 하위 컨테이너 생성을 모두 처리한다.

입력:

동작:

가능한 응답:

새 리소스는 대상 컨테이너 URI에 POST를 사용하여 생성되며, 서버가 최종 식별자를 할당한다. 클라이언트는 Slug 헤더를 통해 이름을 제안할 MAY 있다. 클라이언트는 [RFC8288]의 Web Linking 구문에 따라 POST 요청에 하나 이상의 Link 헤더를 포함하여 새 리소스에 대한 초기 사용자 관리 메타데이터를 제공할 MAY 있다. 서버 관리 메타데이터는 생성 시 서버가 자동으로 생성해야 하며, 클라이언트가 제공한 링크로 재정의되어서는 안 된다.

성공 시, 서버는 새 URI를 Location 헤더에 넣어 201 상태 코드를 반환해야 한다. 서버는 부모 컨테이너 (rel="up")에 대한 링크와 생성된 리소스의 전용 linkset 리소스에 대한 링크 (rel="linkset"; type="application/linkset+json")를 포함하여 핵심 서버 관리 메타데이터에 대한 Link 헤더를 포함해야 한다. 추가 링크는 rel="type"(https://www.w3.org/ns/lws#Container 또는 https://www.w3.org/ns/lws#DataResource를 나타냄)를 포함하는 것이 SHOULD된다. 본문은 비어 있거나 리소스의 최소 표현을 포함할 MAY 있다. 모든 메타데이터 생성 및 링크는 일관성을 유지하기 위해 리소스 생성과 원자적이어야 한다.

POST (컨테이너 URI로)서버가 할당한 이름으로 생성: 기존 컨테이너 안에 새 리소스를 추가하려면 POST를 사용한다. 서버는 리소스에 식별자를 할당하며, 선택적으로 Slug 헤더를 통해 제안될 수 있다. 서버는 Slug 헤더가 명명 규칙 또는 기존 리소스와 충돌하지 않는 경우 이를 존중할 MAY 있다. 클라이언트는 생성할 리소스 유형을 다음과 같이 나타낸다:

예시(새 데이터 리소스를 생성하기 위한 POST):

POST /alice/notes/ HTTP/1.1
Host: example.com
Authorization: Bearer <token>
Content-Type: text/plain
Content-Length: 47
Slug: shoppinglist.txt

milk
eggs
bread
butter
apples
orange juice

이 예시에서 클라이언트는 컨테이너 /alice/notes/에 게시하고 있다. 클라이언트는 text/plain 콘텐츠(식료품 목록)를 제공하고 새 리소스의 이름으로 shoppinglist.txt를 제안한다. /alice/notes/가 존재하고 클라이언트가 권한을 가진 경우, 서버는 새 데이터 리소스를 생성하고 이를 컨테이너의 구성원 관계에 추가한다.

예시(POST에 대한 응답 — 데이터 리소스):

HTTP/1.1 201 Created
Location: /alice/notes/shoppinglist.txt
Content-Type: text/plain; charset=UTF-8
Link: </alice/notes/shoppinglist.txt.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/notes/>; rel="up"
Link: <https://www.w3.org/ns/lws#DataResource>; rel="type"
Content-Length: 0

성공 시, 새 URI를 Location 헤더에 넣어 201 Created를 반환한다. 본문은 비어 있거나 최소 표현일 수 있다. 대상 컨테이너 /alice/notes/가 존재하지 않는 경우, 다른 상태 코드가 더 적절하지 않은 한 서버는 404 오류 상태를 반환해야 한다.

컨테이너 생성:컨테이너를 생성하려면, 클라이언트는 Container 유형을 나타내는 Link 헤더와 함께 기존 부모 컨테이너에 POST를 사용한다. 예:

POST /alice/ HTTP/1.1
Host: example.com
Authorization: Bearer <token>
Content-Length: 0
Slug: notes
Link: <https://www.w3.org/ns/lws#Container>; rel="type"

예시(POST에 대한 응답 — 컨테이너):

HTTP/1.1 201 Created
Location: /alice/notes/
Link: </alice/notes/.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/>; rel="up"
Link: <https://www.w3.org/ns/lws#Container>; rel="type"
Content-Length: 0

이는 /alice/notes/에 새 컨테이너를 생성하며, 서버가 생성한 메타데이터에는 https://www.w3.org/ns/lws#Containerrel="type"이 포함된다.

Create에 대한 추가 참고사항(HTTP 바인딩):

메타데이터 관리 및 검색(생성과 관련): 메타데이터는 주로 읽기 작업을 통해 검색되지만, 생성 중에 만들어진다. 클라이언트는 생성 직후 새 리소스 URI에 GET 또는 HEAD를 사용하여 이를 즉시 검색할 수 있다. 클라이언트는 Prefer 헤더를 사용하여 특정 메타데이터 링크(관계 유형을 통해)와 속성의 포함을 요청할 수 있다.

9.3 리소스 읽기

기존 리소스의 표현 또는 컨테이너의 목록을 검색한다.

리소스 읽기 작업은 HTTP GET 요청(및 헤더 전용 요청을 위한 HEAD)으로 리소스 표현을 요청한다. 동작은 대상 URL이 컨테이너인지 또는 컨테이너가 아닌 리소스(데이터 리소스)인지에 따라 다르다. 서버는 메타데이터를 통해 리소스 유형을 구별해야 한다. 모든 응답은 rel="linkset", rel="up", rel="type"과 같은 핵심 관계에 대한 Link 헤더를 포함하여 제8.1절에 정의된 메타데이터와 통합되어야 한다. 서버는 읽기 중 리소스 상태와 그 메타데이터 사이의 원자성을 보장해야 한다.

GET (컨테이너가 아닌 리소스)리소스의 콘텐츠 검색: 전체 콘텐츠를 얻기 위해 리소스 URI에 GET을 보낸다(권한이 있는 경우). 200 OK, 데이터를 포함한 본문, 그리고 저장된 미디어 유형과 일치하는 Content-Type으로 응답한다. 서버는 부분 검색을 위해 [RFC7233]에 따른 범위 요청을 지원해야 한다. 응답은 동시성 제어 및 캐싱을 위해 ETag 헤더를 포함해야 한다.

예시(파일 GET):

GET /alice/notes/shoppinglist.txt HTTP/1.1
Authorization: Bearer <token>
Accept: text/plain

이는 /alice/notes/shoppinglist.txt의 콘텐츠를 요청하며, 클라이언트가 이를 텍스트 형식으로 원한다는 것을 나타낸다. 리소스가 존재하고 텍스트이며 클라이언트가 접근 권한을 가진다고 가정하면:

HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 34
ETag: "abc123456"
Link: </alice/notes/shoppinglist.txt.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/notes/>; rel="up"
Link: <https://www.w3.org/ns/lws#DataResource>; rel="type"

milk
cheese
bread
guacamole
soda
chocolate bars
hash
eggs

서버는 텍스트 콘텐츠를 반환했다(Content-Length가 나타내는 것처럼 총 34바이트). 콘텐츠는 파일에 저장된 정확한 데이터이다. ETag: "abc123456"은 캐싱 또는 동시성 목적의 버전 식별자이다. 응답에는 메타데이터 발견 가능성을 위한 Link 헤더가 포함되며, uptype과 같은 필수 필드를 가진다.

GET (컨테이너 리소스)컨테이너의 콘텐츠 나열: 대상 URI가 (메타데이터 유형을 통해 결정된) 컨테이너에 해당하는 경우, GET 요청은 컨테이너의 구성원 목록을 반환한다. 응답 본문은 LWS 컨테이너 미디어 유형을 사용하는, 컨테이너 표현 절에 정의된 컨테이너 표현이다. 목록에는 각 구성원에 대한 메타데이터가 포함된다: 리소스 식별자(MUST), 유형(MUST), 미디어 유형(DataResources의 경우 MUST), 크기(SHOULD), 및 수정 타임스탬프(SHOULD).

예시(컨테이너 GET):

GET /alice/notes/ HTTP/1.1
Authorization: Bearer <token>
Accept: application/ld+json

컨테이너가 존재하고 클라이언트가 접근 권한을 가진다고 가정하면:

HTTP/1.1 200 OK
Content-Type: application/lws+json
ETag: "container-etag-789"
Link: </alice/notes/.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/>; rel="up"
Link: <https://www.w3.org/ns/lws#Container>; rel="type"

{
  "@context": "https://www.w3.org/ns/lws/v1",
  "id": "/alice/notes/",
  "type": "Container",
  "totalItems": 2,
  "items": [
    {
      "type": "DataResource",
      "id": "/alice/notes/shoppinglist.txt",
      "mediaType": "text/plain",
      "size": 47,
      "modified": "2025-11-24T12:00:00Z"
    },
    {
      "type": ["DataResource", "http://example.org/customType"],
      "id": "/alice/notes/todo.json",
      "mediaType": "application/json",
      "size": 2048,
      "modified": "2025-11-24T13:00:00Z"
    }
  ]
}

이 예시에서 /alice/notes/컨테이너이다. 응답은 LWS 컨텍스트가 있는 JSON-LD를 사용하며, 필수 메타데이터와 함께 구성원을 나열한다. 각 항목은 type, id, mediaType, size, 및 modified 타임스탬프를 평면 속성으로 포함한다.

모든 경우에, 서버는 응답 헤더에 다음 메타데이터를 포함해야 한다: ETag(구성원 수정 시 변경되는 목록 버전을 나타냄), 그리고 그것이 컨테이너임을 나타내는 rel="type", rel="linkset", 및 rel="up"이 있는 Link 헤더.

HEAD (모든 리소스 또는 컨테이너)헤더/메타데이터만: LWS 서버는 컨테이너와 비컨테이너 모두에 대해 HEAD [RFC9110]를 지원해야 하며, GET과 동일한 헤더(ETag, Content-Type, 메타데이터에 대한 Link 포함)를 반환하되 본문은 반환하지 않는다. 이를 통해 콘텐츠를 전송하지 않고 메타데이터를 검색할 수 있다.

캐싱 및 조건부 요청: LWS는 HTTP 캐싱 의미론을 활용한다. 서버는 If-None-Match(ETags 사용) 또는 If-Modified-Since 헤더를 통한 조건부 요청을 지원해야 한다. 리소스 또는 컨테이너 목록이 변경되지 않은 경우, 중복 전송을 피하기 위해 304 Not Modified로 응답한다. ETags는 동시성 및 캐싱 지원을 위해 모든 GET/HEAD 응답에 제공되어야 한다.

발견 가능성 및 권한 부여: 향상된 발견 가능성을 위해, 서버는 하드코딩된 URI 없이 클라이언트를 안내하는 매개변수와 함께 401 Unauthorized 응답에 WWW-Authenticate 헤더를 포함하는 것이 SHOULD된다. 해당되는 경우 메타데이터 링크를 포함하는 것이 SHOULD된다.

9.4 리소스 갱신

전체 대체 또는 부분 패치를 통해 기존 [served resource]의 상태를 수정한다.

리소스 갱신은 PUT 요청(전체 리소스를 대체) 또는 PATCH 요청(부분 수정을 적용)을 통해 기존 제공되는 리소스의 콘텐츠를 수정한다. 클라이언트는 이러한 작업을 수행하려면 리소스 URL에 대한 쓰기 접근 권한을 가져야 한다. 참고: 이 절은 리소스의 기본 콘텐츠 갱신을 설명한다. 그 메타데이터를 갱신하려면 제9.3.2절을 참조하라. LWS 서버는 리소스 URI에 대한 PUT 및 PATCH 요청을 리소스 콘텐츠에 대한 수정으로만 처리해야 하며, 연결된 linkset 리소스에는 기본적으로 영향을 주지 않아야 한다. 콘텐츠와 메타데이터를 하나의 원자적 작업으로 선택적으로 갱신하려면, 클라이언트는 리소스 URI에 대한 PUT/PATCH 요청에 Link 헤더를 포함하고 'Prefer: set-linkset' 선호사항(RFC 7240에 정의됨)을 지정할 MAY 있다. 이 경우, 서버는 제공된 Link 헤더를 콘텐츠 변경 적용과 더불어 linkset에 대한 대체(PUT의 경우) 또는 부분 갱신(PATCH의 경우)으로 해석해야 한다. 이 동작은 서버에게 OPTIONAL이지만, 지원되는 경우 의도하지 않은 메타데이터 덮어쓰기를 방지하기 위해 Prefer 헤더를 통해 명시적으로 호출되어야 한다. 결합 갱신을 지원하지 않는 서버는 선호사항을 무시하거나 501 Not Implemented로 응답해야 한다.

PUT (전체 리소스 대체) – 리소스 URI에 PUT을 보내며, 본문에는 새 전체 콘텐츠를, Content-Type에는 일치하는 유형(일반적으로 기존 유형과 일관됨)을 포함한다. PUT은 기존 리소스에 대해 멱등적이다. 안전을 위해 현재 ETag와 함께 If-Match를 포함한다(제7.3절 동시성 참조). 불일치하면 412 Precondition Failed 또는 409 Conflict가 발생한다. 검사 없이 갱신은 무조건적이지만 동시 변경을 덮어쓸 위험이 있다. 서버가 리소스에 대해 Etags를 지원하는 경우, If-Match 헤더가 없는 무조건 PUT 요청을 428 Precondition Required 응답으로 거부해야 한다.

예시(리소스를 갱신하기 위한 PUT):

PUT /alice/personalinfo.json HTTP/1.1
Authorization: Bearer <token>
Content-Type: application/json
If-Match: "abc123456"
{
"name": "Alice",
"age": 30,
"city": "New London",
"state": "Connecticut"
}

이 예시에서 클라이언트는 /alice/personalinfo.json의 기존 JSON 리소스를 갱신하고 있다. 이전 GET 또는 HEAD 요청에서 얻은 ETag "abc123456"을 If-Match 헤더에 포함한다. 서버는 이를 현재 ETag와 비교한다. 일치하면, 제공된 JSON으로 콘텐츠를 대체한다. 일치하지 않으면, 서버는 갱신을 거부한다(그 사이 다른 사람이 리소스를 변경했기 때문). 성공 응답: 갱신이 성공하면, 서버는 200 OK로 응답하고 갱신된 표현 또는 일부 확인 정보 (예: 새 콘텐츠 또는 그 일부)를 포함할 수 있다. 또는 서버는 본문 없이 성공을 나타내기 위해 204 No Content로 응답할 수 있다(특히 추가 정보 전달이 필요하지 않은 경우 흔함). 어느 경우든, 서버는 새 버전을 나타내는 새 ETag를 포함하는 것이 SHOULD되며, 본문이 반환되는 경우 Content-Type도 포함할 수 있다. 예:

HTTP/1.1 204 No Content
ETag: "def789012"

이는 클라이언트에게 갱신이 완료되었음을 알리고 새 ETag를 제공한다. 서버가 갱신된 콘텐츠를 반환하기로 선택한 경우, 200 OK를 사용하고 헤더와 함께 본문에 JSON을 포함할 수 있다.

PATCH (부분 갱신) – HTTP PATCH 메서드 [RFC5789]는 클라이언트가 전체 새 콘텐츠를 보내는 대신 리소스에 대한 부분 수정을 지정할 수 있게 한다. 이는 작은 부분만 변경된 큰 리소스에서 전체 콘텐츠를 보내는 것이 비효율적인 경우나, 특정 변경을 적용하고 싶은 동시 편집에서 유용하다. LWS 서버는 [RFC7386]에 정의된 JSON Merge Patch (application/merge-patch+json)를 최소한 지원해야 한다.

리소스 메타데이터 갱신(HTTP PUT / PATCH on Linkset) 리소스의 메타데이터는 rel="linkset"이 있는 Link 헤더를 통해 발견되는 해당 linkset 리소스를 수정하여 갱신된다. 전체 대체(PUT): 전체 linkset 문서를 본문에 담아 linkset 리소스 URI에 PUT 요청을 보내면 리소스의 모든 메타데이터가 대체된다. 부분 갱신(PATCH): linkset 리소스 URI에 대한 PATCH 요청은 특정 링크를 추가, 제거 또는 수정한다.

메타데이터에 대한 동시성 제어 리소스의 메타데이터는 여러 행위자가 수정할 수 있으므로, 동시 덮어쓰기를 방지하는 것이 중요하다. 데이터 무결성을 보장하기 위해, LWS 서버와 클라이언트는 linkset 리소스에 대한 모든 PUT 및 PATCH 작업에서 조건부 요청 [RFC7232]을 사용하는 낙관적 동시성 제어를 구현해야 한다. 서버 책임: 서버는 linkset 리소스에 대한 GET 및 HEAD 요청 응답에 Etag 헤더를 포함해야 한다. linkset에 대한 PUT 또는 PATCH가 성공하면, 서버는 수정된 linkset에 대해 새롭고 고유한 Etag 값을 생성하고 응답의 Etag 헤더에 반환해야 한다. 클라이언트 책임: linkset 리소스를 수정할 때, 클라이언트는 해당 리소스에 대해 가장 최근에 받은 Etag를 포함하는 If-Match 헤더를 포함해야 한다. 처리 규칙: If-Match 헤더 값이 linkset의 현재 Etag와 일치하지 않으면, 서버는 412 Precondition Failed 상태 코드로 요청을 거부해야 한다. linkset URI에 대한 PUT 또는 PATCH 요청에서 If-Match 헤더가 누락된 경우, 서버는 428 Precondition Required 상태 코드 [RFC6585]로 요청을 거부해야 한다. 예시(linkset을 대체하기 위한 PUT): 클라이언트가 먼저 linkset을 가져오고 그 ETag를 받는다.

GET /alice/personalinfo.json.meta HTTP/1.1
Authorization: Bearer <token>
Accept: application/linkset+json
HTTP/1.1 200 OK
Content-Type: application/linkset+json
ETag: "meta-v1"
{
  "linkset": [
    {
      "anchor": "/alice/personalinfo.json",
      "describedby": [ { "href": "/schemas/personal-info.json" } ]
    }
  ]
}

이제 클라이언트는 라이선스를 추가하려 한다. 새롭고 완전한 linkset 문서를 구성하고 If-Match 헤더와 함께 PUT 요청을 보낸다.

PUT /alice/personalinfo.json.meta HTTP/1.1
Authorization: Bearer <token>
Content-Type: application/linkset+json
If-Match: "meta-v1"
{
  "linkset": [
    {
      "anchor": "/alice/personalinfo.json",
      "describedby": [ { "href": "/schemas/personal-info.json" } ],
      "license": [ { "href": "https://creativecommons.org/licenses/by/4.0/" } ]
    }
  ]
}

성공하면, 서버는 성공과 새 ETag로 응답한다.

HTTP/1.1 204 No Content
ETag: "meta-v2"

갱신 규칙 요약 리소스의 콘텐츠만 변경하려는 경우 → 리소스 자체에 PUT/PATCH한다. 리소스의 링크(메타데이터)만 변경하려는 경우 → 리소스와 연결된 linkset 리소스에 PUT/PATCH한다. 콘텐츠와 링크를 모두 변경하려는 경우 → 적절한 Link 헤더와 'Prefer: set-linkset'을 포함하여 리소스 자체에 PUT/PATCH한다. 둘을 모두 설정하는 것은 기본적으로 꺼져 있다.

9.5 리소스 삭제

리소스와 그 연결된 메타데이터를 영구적으로 제거한다.

리소스 삭제 작업은 위의 추상 작업에서 정의한 대로 HTTP DELETE 메서드를 사용하여 구현된다. 이 절은 입력, 동작 및 응답에 대한 HTTP 바인딩을 지정한다.

DELETE 요청은 제거할 리소스 또는 컨테이너의 URI를 대상으로 한다. 클라이언트는 동시성 검사를 위해 ETag가 있는 If-Match 헤더를 포함할 MAY 있다.

삭제 및 포함 관계: 리소스가 삭제되면, 서버는 이를 부모 컨테이너items 목록에서 원자적으로 제거해야 한다. 부모 컨테이너의 totalItems 개수는 그에 따라 갱신되는 것이 SHOULD되며, 그 ETag는 변경을 반영하도록 갱신되어야 한다.

컨테이너가 아닌 리소스의 경우, 서버는 리소스 콘텐츠, 그 연결된 메타데이터(linkset 리소스), 그리고 부모 컨테이너포함 관계 참조를 제거한다.

컨테이너 리소스의 경우, 서버는 기본적으로 비재귀 삭제를 사용한다. 컨테이너가 비어 있지 않고 재귀가 요청되지 않은 경우, 서버는 409 Conflict로 요청을 거부해야 한다. 서버는 삭제되는 컨테이너 내의 모든 포함 리소스에 대한 재귀 삭제를 지원할 MAY 있다. 클라이언트는 [RFC4918]에 정의된 대로 재귀 삭제를 요청하기 위해 Depth: infinity 헤더를 사용해야 한다.

성공 시, 서버는 204 No Content로 응답해야 한다. 서버는 [RFC9110]에 정의된 조건부 요청을 지원하는 것이 SHOULD된다.

클라이언트에게 권한이 없는 경우, 서버는 403 Forbidden(클라이언트의 식별자는 알려져 있지만 권한이 부족한 경우) 또는 401 Unauthorized(유효한 인증이 제공되지 않은 경우)를 반환해야 한다. 리소스 존재를 드러내는 것이 보안 위험을 야기하는 경우, 서버는 대신 404 Not Found를 반환할 MAY 있다.

예시(컨테이너가 아닌 리소스 DELETE):

DELETE /alice/notes/shoppinglist.txt HTTP/1.1
Authorization: Bearer <token>
If-Match: "abc123456"

ETag가 일치하고 클라이언트가 권한을 가진다고 가정하면, 서버는 리소스와 그 메타데이터를 삭제하고 이를 부모 컨테이너 /alice/notes/에서 원자적으로 제거한다:

HTTP/1.1 204 No Content

예시(재귀 없이 비어 있지 않은 컨테이너 DELETE):

DELETE /alice/notes/ HTTP/1.1
Authorization: Bearer <token>

/alice/notes/에 리소스가 포함되어 있다고 가정하면, 서버는 삭제를 거부한다:

HTTP/1.1 409 Conflict
Content-Type: text/plain

Cannot delete container /alice/notes/ - container is not empty.

예시(지원되는 경우 재귀로 컨테이너 DELETE):

DELETE /alice/notes/ HTTP/1.1
Authorization: Bearer <token>
Depth: infinity

서버가 재귀를 지원하고 클라이언트가 모든 콘텐츠에 대한 권한을 가진다고 가정하면, 서버는 컨테이너와 그 하위 항목을 원자적으로 삭제한다:

HTTP/1.1 204 No Content

9.6 HTTP 상태 매핑 요약

이 표는 일관성을 위해 일반 LWS 응답 (제8절에서)를 HTTP 상태 코드와 페이로드에 매핑하며, 페이지네이션, 동시성 제어, 할당량 제약 및 메타데이터 통합과 같은 특정 시나리오를 포함한다:

LWS 응답 HTTP 상태 코드 HTTP 페이로드
성공 (읽기 또는 갱신, 데이터 반환) 200 OK 응답 본문에 있는 리소스 표현(GET의 경우 또는 PUT/PATCH가 콘텐츠를 반환하는 경우), 관련 헤더 (Content-Type, ETag, rel="linkset", rel="up"과 같은 메타데이터용 Link)와 함께. 컨테이너 목록의 경우, 규범적 컨텍스트와 구성원 메타데이터(IDs, types, sizes, timestamps)를 가진 JSON-LD를 포함한다.
Created (새 리소스) 201 Created 일반적으로 응답 본문 없음(또는 새 리소스의 최소 표현). Location 헤더는 새 리소스의 URI로 설정된다. 동시성을 위한 ETag 같은 헤더와 서버 관리 메타데이터에 대한 Link 헤더가 포함되어야 한다.
Deleted (반환할 콘텐츠 없음) 204 No Content 응답 본문 없음. 리소스가 삭제되었거나 요청이 성공했고 더 말할 내용이 없음을 나타낸다. 서버는 영구 삭제에 410 Gone을 사용할 MAY 있다.
Bad Request (잘못된 입력 또는 제약 조건) 400 Bad Request 무엇이 잘못되었는지 설명하는 오류 세부사항. 서버는 구조화된 오류 응답을 위해 [RFC9457]에 정의된 표준 형식을 사용하는 것이 SHOULD되며, 예를 들어 "type", "title", "status", "detail", "instance"와 같은 필드를 가진 JSON 객체를 사용할 수 있다.

10. 접근 요청 및 허가

접근 요청 및 허가는 에이전트가 리소스에 대한 접근을 요청하고, 스토리지 컨트롤러가 정의된 제약 조건과 함께 접근을 허가하기 위한 메커니즘을 제공한다. 접근을 요청하고 허가하기 위한 엔드포인트는 특수한 수신함의 한 유형으로 동작한다.

에이전트접근 허가를 권한 부여 토큰으로 서버에 제시하지 않는다. 오히려 접근 허가는 무엇이, 누구에게, 어떤 제약 조건 아래에서 권한 부여되었는지에 대한 기록 역할을 한다. 접근 허가가 생성되거나 철회(삭제)될 때, 그 변경을 반영하도록 기반 접근 정책을 조정하는 것은 서버의 책임이다. 접근 허가 엔드포인트와 특정 정책 집행 계층 사이의 상호작용은 이 명세의 범위를 벗어난다.

이 절에서 정의하는 접근 프로파일은 동작, 제약 조건 및 피할당자를 포함하여 Open Digital Rights Language (ODRL)의 개념을 기반으로 한다. 다른 프로파일은 다른 개념적 프레임워크를 사용할 수 있다.

이슈: 주요 용어 절과 통합

이 절은 다음 용어를 정의한다:

  • 접근 요청에이전트가 제출하는 데이터 객체로, 원하는 범위와 제약 조건을 포함하여 스토리지 리소스에 대해 특정 동작을 수행하기 위한 요청을 표현한다.
  • 접근 허가스토리지 컨트롤러가 생성하는 데이터 객체로, 특정 정의된 제약 조건 내에서 에이전트스토리지 리소스에 대해 특정 동작을 수행할 수 있는 능력을 표현한다.
  • 접근 프로파일 — 접근 프로파일은 유효한 접근 정책을 표현하기 위한 요구사항을 설명한다. 모든 접근 프로파일은 URI로 식별되며, 서버는 자신의 스토리지 설명 리소스에 있는 서비스 객체의 conformsTo 속성에서 이를 참조하여 하나 이상의 접근 프로파일 지원을 나타낸다.

10.1 발견

스토리지는 자신의 스토리지 설명 리소스에서 접근 요청접근 허가에 대한 지원을 알릴 MAY 있다. 이러한 지원이 광고되는 경우, 접근 요청을 위한 엔드포인트를 설명하는 서비스 객체는 문자열 AccessRequestService와 같은 type을 가져야 하며, 접근 허가를 위한 엔드포인트를 설명하는 서비스 객체는 문자열 AccessGrantService와 같은 type을 가져야 한다. 서비스 객체는 해당 엔드포인트에서 지원되는 접근 프로파일을 식별하는 하나 이상의 URI 컬렉션을 값으로 갖는 conformsTo 속성을 포함하는 것이 SHOULD된다. 추가 속성이 포함될 MAY 있다:

10: 접근 요청 및 허가 서비스가 있는 스토리지 설명
{
  "@context": [
    "https://www.w3.org/ns/lws/v1"
  ],
  "id": "https://storage.example/",
  "type": "Storage",
  "service": [
    {
      "type": "AccessRequestService",
      "serviceEndpoint": "https://access.example/request/",
      "conformsTo": ["https://www.w3.org/ns/lws#AccessProfile"]
    },
    {
      "type": "AccessGrantService",
      "serviceEndpoint": "https://access.example/grant/",
      "conformsTo": ["https://www.w3.org/ns/lws#AccessProfile"]
    }
  ]
}

10.2 데이터 모델

접근 요청 또는 접근 허가는 식별 및 라우팅을 위한 속성뿐 아니라, 요청되거나 허용된 작업을 설명하는 access 객체를 표현하는 데이터 객체이다. ODRL 개념을 사용하여 접근 요청을 설명하는 프로파일은 10.3 접근 프로파일에 설명되어 있다.

다음 예시는 접근 요청을 보여준다. 이 예시는 10.4.1 JSON-LD 직렬화에 정의된 JSON-LD 직렬화를 사용하여 표시된다.

11: 접근 요청
{
  "@context": [
    "https://www.w3.org/ns/lws/v1"
  ],
  "type": ["AccessRequest"],
  "inbox": "https://id.example/agent/inbox/",
  "storage": "https://storage.example/",
  "access": [{
    "type": ["AccessPolicy"],
    "action": ["read", "create"],
    "assignee": "https://id.example/agent",
    "target": {
      "type": "StorageResource",
      "value": ["https://storage.example/projects/"]
    },
    "constraint": [
      {
        "leftOperand": "purpose",
        "operator": "eq",
        "rightOperand": "https://purpose.example/collaboration"
      },
      {
        "leftOperand": "dateTime",
        "operator": "lteq",
        "rightOperand": "2026-06-09T10:00:00Z"
      }
    ]
  }]
}

다음 예시는 접근 허가를 보여준다. 이 예시는 10.4.1 JSON-LD 직렬화에 정의된 JSON-LD 직렬화를 사용하여 표시된다.

12: 접근 허가
{
  "@context": [
    "https://www.w3.org/ns/lws/v1"
  ],
  "type": ["AccessGrant"],
  "storage": "https://storage.example/",
  "access": [{
    "type": ["AccessPolicy"],
    "action": ["read"],
    "assignee": "https://id.example/agent",
    "target": {
      "type": "StorageResource",
      "value": ["https://storage.example/projects/"]
    },
    "constraint": [
      {
        "leftOperand": "purpose",
        "operator": "eq",
        "rightOperand": "https://purpose.example/collaboration"
      },
      {
        "leftOperand": "dateTime",
        "operator": "lteq",
        "rightOperand": "2026-06-09T10:00:00Z"
      }
    ]
  }]
}

접근 요청접근 허가에는 다른 속성이 존재할 MAY 있다.

10.2.1 유형

type 속성은 문서의 유형을 표현한다.

type 속성의 값은 하나 이상의 termsabsolute URL strings이어야 한다. 접근 요청의 경우, 값은 AccessRequest term을 포함해야 한다. 접근 허가의 경우, 값은 AccessGrant term을 포함해야 한다. 추가 유형 값이 포함될 MAY 있다.

이 속성은 REQUIRED이다.

이 문서는 접근 요청접근 허가에 대해 다음 유형 값을 정의한다:

  • AccessRequest — 리소스에 대한 접근을 요청하는 에이전트의 요청.
  • AccessGrant — 리소스에 대한 접근을 허가하는 스토리지 컨트롤러의 권한 부여.
13: type 속성
{
  "type": ["AccessGrant"]
}

10.2.2 스토리지

storage 속성은 접근 요청 또는 접근 허가의 범위가 지정되는 LWS 스토리지를 식별한다.

storage 속성의 값은 URI여야 한다.

이 속성은 REQUIRED이다.

14: storage 속성
{
  "storage": "https://storage.example/"
}

10.2.3 수신함

inbox 속성은 접근 요청 또는 접근 허가와 관련된 알림을 받기 위한 URI를 지정한다 (10.6 알림 참조).

inbox 속성의 값은 URI여야 한다.

이 속성은 OPTIONAL이다.

15: inbox 속성
{
  "inbox": "https://id.example/agent/inbox/"
}

10.2.4 접근

access 속성은 서버가 지원하는 프로파일을 기반으로, 하나 이상의 접근 프로파일의 특성을 설명한다. ODRL Information Model을 기반으로 하는 프로파일은 10.3 접근 프로파일에 설명되어 있다.

access 속성의 값은 하나 이상의 객체 컬렉션이어야 한다.

이 속성은 REQUIRED이다.

10.3 접근 프로파일

이 명세는 ODRL Information ModelODRL Vocabulary를 기반으로 하는 접근 프로파일을 정의하며, 다음 URL로 식별된다: https://www.w3.org/ns/lws#AccessProfile.

10.3.1 유형

type 속성은 접근 정책의 유형을 표현한다.

type 속성의 값은 하나 이상의 termsabsolute URL strings이어야 하며, AccessPolicy term을 포함해야 한다. 추가 유형 값이 포함될 MAY 있다.

이 속성은 REQUIRED이다.

16: 접근 정책 유형
{
  "access": [{
    "type": ["AccessPolicy"]
  }]
}

10.3.2 동작

action 속성은 에이전트가 (요청의 경우) 수행하기를 원하는, 또는 (허가의 경우) 수행할 권한이 부여된 작업을 설명한다.

action 속성의 값은 하나 이상의 문자열 컬렉션이어야 한다. 각 값은 서버가 인식하는 작업에 해당해야 한다. 다음 값은 지원되어야 한다: read, modify, create, 및 delete. read, modify, 및 delete 값은 ODRL Vocabulary가 정의한다. create 값은 이 명세가 정의한다.

이러한 동작 값은 다음과 같이 LWS 작업에 대응한다:

  • read — 리소스 또는 그 메타데이터를 검색한다(HTTP GET, HEAD)
  • modify — 기존 리소스를 수정한다(HTTP PUT, PATCH)
  • create — 컨테이너 안에 새 리소스를 생성한다(HTTP POST)
  • delete — 기존 리소스를 제거한다(HTTP DELETE)

이 속성은 REQUIRED이다.

17: action 속성
{
  "access": [{
    "action": ["read", "create"]
  }]
}

10.3.3 피할당자

assignee 속성은 (요청의 경우) 접근을 요청하는 당사자 또는 (허가의 경우) 접근을 부여받는 당사자를 식별한다.

assignee 속성의 값은 URI여야 한다. 공개 접근은 FOAF vocabularyAgent 클래스를 사용하여 할당될 MAY 있으며, 이는 URI http://xmlns.com/foaf/0.1/Agent로 식별된다.

이 속성은 REQUIRED이다.

18: assignee 속성
{
  "access": [{
    "assignee": "https://id.example/agent"
  }]
}

10.3.4 대상

target 속성은 접근 요청 또는 접근 허가가 적용되는 리소스를 식별한다.

target 속성은 다음 속성을 포함하는 객체여야 한다:

  • type — 대상 매처의 유형을 식별하는 term 또는 absolute URL string.
  • value — 대상 리소스를 식별하는 데 사용되는 하나 이상의 문자열 컬렉션.

이 명세는 target 객체와 함께 사용하기 위한 다음 type 값을 정의한다:

  • https://www.w3.org/ns/lws#DataResourcelws:DataResource 유형의 리소스와 일치한다.
  • https://www.w3.org/ns/lws#Containerlws:Container 유형의 리소스와 일치한다.
  • https://www.w3.org/ns/lws#StorageResource스토리지가 관리하는 모든 리소스와 일치한다.

서버는 추가 유형 값을 지원할 MAY 있다.

이 속성은 OPTIONAL이다.

19: 리소스 유형이 있는 target 속성
{
  "access": [{
    "target": {
      "type": "StorageResource",
      "value": [
        "https://storage.example/data/2025",
        "https://storage.example/data/2026"
      ]
    }
  }]
}

10.3.5 제약 조건

constraint 속성은 요청되거나 허가되는 접근을 제한하거나 한정하는 조건을 정의한다. 이 속성은 ODRL Constraint 모델을 사용한다.

constraint 속성의 값은 존재하는 경우 제약 조건 객체 컬렉션이어야 한다. 각 제약 조건 객체는 다음 속성을 포함해야 한다:

  • leftOperand — 제약되는 피연산자를 식별하는 문자열.
  • operator — 비교 연산자를 식별하는 문자열.
  • rightOperand — 비교 대상 값. 유형은 leftOperand에 따라 달라진다.

여러 제약 조건 객체가 존재하는 경우, 그 모두가 충족되어야 한다.

이 프로파일에 대한 지원을 알리는 서버는 다음 leftOperand 값을 지원해야 한다:

  • client — HTTP 요청에 대한 클라이언트 식별자를 나타냄
  • mediaType — 대상 HTTP 리소스의 미디어 유형을 나타냄
  • type — 리소스의 link 헤더에 표현된 유형 URL을 나타냄
  • purpose — 요청되거나 허가되는 접근의 의도된 사용을 나타냄
  • dateTime — 현재 날짜와 시간을 나타냄

이 속성은 OPTIONAL이다.

다음 예시는 이러한 제약 조건의 사용을 보여준다:

10.3.5.1 목적 제약 조건

다음 예시는 요청되거나 허가되는 접근의 의도된 사용을 설명하기 위해 purposeleftOperand 값을 사용한다. eq 연산자가 사용되는 경우, rightOperand 값은 목적을 식별하는 URI이다. isAnyOf 연산자가 사용되는 경우, rightOperand 값은 목적 URI의 배열이며, 명시된 목적이 나열된 값 중 하나와 일치하면 제약 조건이 충족된다:

20: 목적 제약 조건
{
  "access": [{
    "constraint": [
      {
        "leftOperand": "purpose",
        "operator": "isAnyOf",
        "rightOperand": [
          "https://purpose.example/collaboration",
          "https://purpose.example/research"
        ]
      }
    ]
  }]
}
10.3.5.2 클라이언트 제약 조건

다음 예시는 특정 클라이언트 애플리케이션으로 접근을 제한하기 위해 clientleftOperand 값을 사용한다. eq 연산자가 사용되는 경우, rightOperand 값은 클라이언트를 식별하는 URI이다:

21: 클라이언트 제약 조건
{
  "access": [{
    "constraint": [
      {
        "leftOperand": "client",
        "operator": "eq",
        "rightOperand": "https://app.example/client-id"
      }
    ]
  }]
}
10.3.5.3 미디어 유형 제약 조건

다음 예시는 특정 미디어 유형을 가진 리소스로 접근을 제한하기 위해 mediaTypeleftOperand 값을 사용한다. eq 연산자가 사용되는 경우, rightOperand 값은 IANA 미디어 유형을 식별하는 문자열이다. isAnyOf 연산자가 사용되는 경우, rightOperand 값은 미디어 유형 문자열의 배열이며, 리소스의 미디어 유형이 나열된 값 중 하나와 일치하면 접근이 허용된다:

22: 미디어 유형 제약 조건
{
  "access": [{
    "constraint": [
      {
        "leftOperand": "mediaType",
        "operator": "isAnyOf",
        "rightOperand": ["image/jpeg", "image/png"]
      }
    ]
  }]
}
10.3.5.4 리소스 유형 제약 조건

모든 LWS 리소스는 유형 값을 나타내는 link 헤더를 포함한다:

다음 예시는 HTTP Link 헤더에 광고된 리소스 유형을 기반으로 접근을 제한하기 위해 typeleftOperand 값을 사용한다. eq 연산자가 사용되는 경우, rightOperand 값은 리소스 유형을 식별하는 URI이다. isAnyOf 연산자가 사용되는 경우, rightOperand 값은 유형 URI의 배열이며, 리소스의 유형이 나열된 값 중 하나와 일치하면 접근이 허용된다:

24: 리소스 유형 제약 조건
{
  "access": [{
    "constraint": [
      {
        "leftOperand": "type",
        "operator": "isAnyOf",
        "rightOperand": [
          "https://type.example/Playlist",
          "https://type.example/Song"
        ]
      }
    ]
  }]
}
10.3.5.5 시간 제약 조건

다음 예시는 특정 시간 창으로 접근을 제한하기 위해 dateTimeleftOperand 값을 사용한다. gteq 연산자는 창의 시작을 정의하고 lteq 연산자는 끝을 정의한다. 시간 제약 조건에 대한 rightOperand 값은 XML Schema dateTime 문자열이다:

25: 시간 제약 조건
{
  "access": [{
    "constraint": [
      {
        "leftOperand": "dateTime",
        "operator": "gteq",
        "rightOperand": "2026-03-09T12:00:00Z"
      },
      {
        "leftOperand": "dateTime",
        "operator": "lteq",
        "rightOperand": "2026-06-09T10:00:00Z"
      }
    ]
  }]
}
10.3.5.6 제약 조건 결합

여러 제약 조건 객체가 존재하는 경우, 접근이 허용되려면 그 모두가 충족되어야 한다. 다음 예시는 특정 날짜 이전에 특정 클라이언트 애플리케이션으로 접근을 제한한다:

26: 결합된 제약 조건
{
  "access": [{
    "action": ["read"],
    "assignee": "https://id.example/agent",
    "target": {
      "type": "StorageResource",
      "value": ["https://storage.example/projects/"]
    },
    "constraint": [
      {
        "leftOperand": "dateTime",
        "operator": "lteq",
        "rightOperand": "2026-06-09T10:00:00Z"
      },
      {
        "leftOperand": "client",
        "operator": "eq",
        "rightOperand": "https://app.example/client-id"
      }
    ]
  }]
}

10.4 직렬화

이 절에서 정의된 데이터 모델은 특정 직렬화와 독립적이다.

10.4.1 JSON-LD 직렬화

이 명세는 접근 요청접근 허가에 대한 JSON-LD 직렬화를 정의한다. 이 직렬화를 사용하는 문서는 https://www.w3.org/ns/lws/v1을 포함하는 순서 있는 집합을 값으로 갖는 @context 속성을 포함해야 한다. 확장 terms를 정의하기 위해 추가 context 항목이 포함될 MAY 있다.

이 직렬화와 연결된 미디어 유형은 application/lws+json이다.

27: JSON-LD @context
{
  "@context": [
    "https://www.w3.org/ns/lws/v1"
  ]
}

10.5 프로토콜

접근 요청접근 허가 엔드포인트는 LWS 컨테이너이며, 이 명세에 정의된 규칙을 준수해야 한다.

이러한 엔드포인트는 최소한 GET 및 POST 작업 지원을 필요로 한다. DELETE 작업은 RECOMMENDED된다. 다른 작업이 지원될 MAY 있다.

이러한 엔드포인트는 요청 및 응답 페이로드 모두에 대해 10.4.1 JSON-LD 직렬화에 정의된 JSON-LD 직렬화를 지원해야 한다. 서버는 추가 직렬화를 지원할 MAY 있다.

에이전트접근 요청 엔드포인트에 POST 요청을 제출하여 접근 요청을 생성한다. 스토리지 컨트롤러접근 허가 엔드포인트에 POST 요청을 제출하여 접근 허가를 생성한다.

성공적인 POST 작업은 새 리소스의 URL로 설정된 Location 헤더로 응답해야 한다.

10.5.1 접근 요청 엔드포인트

  • POST / — 접근 요청을 생성한다.
  • GET / — 접근 요청 목록을 검색한다.
  • GET /:id — 특정 접근 요청을 검색한다.
  • DELETE /:id — 접근 요청을 취소한다.

10.5.2 접근 허가 엔드포인트

  • POST / — 접근 허가를 생성한다.
  • GET / — 접근 허가 목록을 검색한다.
  • GET /:id — 특정 접근 허가를 검색한다.
  • DELETE /:id — 접근 허가를 철회한다.

10.6 알림

Issue 103: LWS 알림 기능 work-item

이 절은 아직 정의되지 않은 LWS의 알림 절과 정렬되어야 한다.

알림은 에이전트스토리지 컨트롤러에게 접근 요청접근 허가의 변경을 알리기 위한 메커니즘을 제공한다. 접근 요청 또는 접근 허가inbox 속성이 존재하는 경우, 서버는 해당 엔드포인트로 알림을 전달하여 피할당자에게 이벤트를 알리는 것이 SHOULD된다.

알림의 직렬화는 LWS 알림 데이터 모델의 요구사항을 준수해야 한다.

inbox 엔드포인트로 전달되는 알림은 알림 전달에 대해 LWS 프로토콜에 정의된 요구사항을 준수해야 한다.

참고

이 절에서 설명하는 알림 메커니즘은 Linked Data Notifications 패턴과 유사하며, 여기서 알림은 inbox 속성을 통해 발견되고, 해당 수신함으로 POST 요청을 보내 전달된다.

10.6.1 알림 이벤트

서버는 다음 이벤트에 대한 응답으로 알림을 보내는 것이 SHOULD된다:

서버는 다른 이벤트에 대한 응답으로 알림을 보낼 MAY 있다.

11. LWS 미디어 유형

11.1 LWS 미디어 유형

LWS 컨테이너 표현스토리지 설명 리소스는 미디어 유형 application/lws+json을 사용해야 한다.

LWS 컨테이너 표현은 JSON-LD 규약을 사용하지만, LWS의 제약 조건과 요구사항은 특정 미디어 유형의 사용을 정당화한다. LWS 컨테이너는 JSON-LD의 제한된 프로파일로 간주될 수 있으므로, 구현은 application/ld+json; profile="https://www.w3.org/ns/lws/v1" 미디어 유형을 application/lws+json과 동등한 것으로 간주하는 것이 SHOULD된다.

11.1.1 콘텐츠 협상

서버는 컨테이너 표현에 대한 콘텐츠 협상을 지원해야 한다. 응답 페이로드는 요청된 미디어 유형과 관계없이 동일해야 하며 — Content-Type 응답 헤더만 달라진다:

  • 클라이언트가 application/lws+json을 요청하는 경우, 서버는 Content-Type: application/lws+json으로 응답해야 한다.
  • 클라이언트가 application/ld+json을 요청하는 경우, 서버는 Content-Type: application/ld+json으로 응답해야 한다.
  • 클라이언트가 application/json을 요청하는 경우, 서버는 Content-Type: application/json으로 응답해야 한다.

세 경우 모두 응답 본문은 LWS 컨테이너 어휘를 준수하는 동일한 JSON-LD 문서이다. 서버는 콘텐츠 협상을 통해 추가 미디어 유형(예: text/turtle)을 자유롭게 지원할 수 있다.

11.1.2 페이지네이션

컨테이너와 같은 특정 복합 리소스는 많은 수의 리소스를 보유할 수 있다. 클라이언트가 목록을 점진적으로 검색할 수 있도록, 서버는 구성원 수가 서버가 정한 임계값을 초과하는 컨테이너에 대해 페이지네이션을 지원하는 것이 SHOULD된다.

11.1.2.1 페이지네이션 모델

페이지네이션은 링크 기반이다. 서버는 HTTP Link 헤더 [RFC8288]를 통해 페이지네이션 URI를 제공하며, 클라이언트가 숫자 오프셋에 의존하지 않고 전체 목록을 탐색할 수 있게 한다.

목록이 페이지네이션되는 경우, 응답 본문은 현재 페이지의 항목만 포함한다. 복합 리소스의 id, type, 및 totalItems 속성은 전체 구성원 관계를 반영하며, items는 현재 페이지의 리소스만 포함한다.

11.1.2.3 페이지 요청

클라이언트는 첫 번째 페이지를 얻기 위해 복합 리소스의 URI를 요청한다. 응답에는 클라이언트가 후속 페이지를 검색하기 위해 따라갈 페이지네이션 Link 헤더가 포함된다. 서버는 이전 스캔 중 얻은 페이지네이션 URI를 통해 특정 페이지에 직접 접근하는 것도 지원할 MAY 있다.

페이지네이션된 응답이 반환되는 경우, 서버는 200 OK로 응답해야 한다. 응답 본문의 totalItems 속성은 현재 페이지뿐 아니라 모든 페이지에 걸친 총 항목 수를 반영하는 것이 SHOULD된다.

11.1.2.4 예: 페이지네이션된 컨테이너

요청:

GET /alice/photos/ HTTP/1.1
Authorization: Bearer <token>
Accept: application/lws+json

응답(첫 번째 페이지):

HTTP/1.1 200 OK
Content-Type: application/lws+json
ETag: "photos-page1-etag"
Link: </alice/photos/.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/>; rel="up"
Link: </alice/photos/.acl>; rel="acl"
Link: <https://www.w3.org/ns/lws#Container>; rel="type"
Link: </alice/photos/?page=1>; rel="first"
Link: </alice/photos/?page=3>; rel="last"
Link: </alice/photos/?page=2>; rel="next"

{
  "@context": "https://www.w3.org/ns/lws/v1",
  "id": "/alice/photos/",
  "type": "Container",
  "totalItems": 150,
  "items": [
    {
      "type": "DataResource",
      "id": "/alice/photos/vacation.jpg",
      "mediaType": "image/jpeg",
      "size": 248392,
      "modified": "2025-11-20T10:30:00Z"
    },
    {
      "type": "DataResource",
      "id": "/alice/photos/portrait.png",
      "mediaType": "image/png",
      "size": 102400,
      "modified": "2025-11-21T14:15:00Z"
    }
  ]
}

요청(다음 페이지):

GET /alice/photos/?page=2 HTTP/1.1
Authorization: Bearer <token>
Accept: application/lws+json

응답(중간 페이지):

HTTP/1.1 200 OK
Content-Type: application/lws+json
ETag: "photos-page2-etag"
Link: </alice/photos/.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/>; rel="up"
Link: </alice/photos/.acl>; rel="acl"
Link: <https://www.w3.org/ns/lws#Container>; rel="type"
Link: </alice/photos/?page=1>; rel="first"
Link: </alice/photos/?page=1>; rel="prev"
Link: </alice/photos/?page=3>; rel="next"
Link: </alice/photos/?page=3>; rel="last"

{
  "@context": "https://www.w3.org/ns/lws/v1",
  "id": "/alice/photos/",
  "type": "Container",
  "totalItems": 150,
  "items": [
    {
      "type": "DataResource",
      "id": "/alice/photos/sunset.jpg",
      "mediaType": "image/jpeg",
      "size": 315000,
      "modified": "2025-11-22T09:00:00Z"
    }
  ]
}

12. JSON-LD 컨텍스트 및 어휘

12.1 JSON-LD 컨텍스트 및 어휘

12.1.1 규범적 JSON-LD 컨텍스트

컨테이너 표현은 다음 @context 값을 포함해야 한다:

"@context": "https://www.w3.org/ns/lws/v1"

규범적 JSON-LD 컨텍스트 문서는 컨테이너 표현에서 사용되는 짧은 속성 이름과 LWS 및 관련 어휘의 전체 URI 사이의 매핑을 정의한다. 컨텍스트는 다음과 같이 정의된다:

{
  "@context": {
    "@version": 1.1,
    "@protected": true,
    "lws": "https://www.w3.org/ns/lws#",
    "as": "https://www.w3.org/ns/activitystreams#",
    "schema": "https://schema.org/",
    "xs": "http://www.w3.org/2001/XMLSchema#",
    "id": "@id",
    "type": "@type",
    "Container": "lws:Container",
    "DataResource": "lws:DataResource",
    "items": "lws:items",
    "totalItems": "as:totalItems",
    "mediaType": "as:mediaType",
    "size": {
      "@id": "schema:size",
      "@type": "xs:long"
    },
    "modified": {
      "@id": "as:updated",
      "@type": "xs:dateTime"
    }
  }
}

컨텍스트는 @protected이며, 이는 term 정의가 다른 컨텍스트에 의해 재정의될 수 없도록 보장한다.

12.1.2 어휘

LWS 어휘는 컨테이너 표현에서 사용되는 다음 유형과 속성을 정의한다:

유형:

Term URI 설명
Container lws:Container 다른 리소스를 포함하는 리소스
DataResource lws:DataResource 데이터를 담고 있는 리소스

속성:

Term URI 설명
items lws:items 컨테이너에 포함된 리소스의 목록
totalItems as:totalItems 포함된 리소스의 총 개수
mediaType as:mediaType 리소스의 미디어 유형
size schema:size 바이트 단위 리소스 크기
modified as:updated 리소스가 마지막으로 수정된 날짜-시간

13. 리소스 식별

URI 스킴, 리소스 명명 규약 및 해석 메커니즘을 포함하여 LWS Protocol 내에서 리소스가 어떻게 식별되고 주소 지정되는지 정의한다. 이 절은 다른 절(예: Resource Access) 안으로 이동될 수 있다

이 부분은 의도적으로 비워 둔다

14. 이식성 고려사항

LWS 구현이 상호 운용성을 유지하면서 다양한 플랫폼, 환경 및 스토리지 백엔드에서 작동할 수 있도록 보장하기 위한 고려사항을 설명하고, 스토리지 제공자 변경을 가능하게 하는 affordance를 제공한다

이 부분은 의도적으로 비워 둔다

15. 보안 고려사항

이 절은 비규범적이다.

보안 LWS 배포를 위한 위협 모델, 보안 요구사항 및 구현 지침을 다루는 공식 보안 고려사항 절.

OAuth 2.0 Security에 대한 Best Current Practice [RFC9700]에 설명된 권고사항이 이 명세에 적용된다.

15.1 전송 보안

이 절은 비규범적이다.

Transport Layer Security (TLS)는 변조, 스푸핑 및 정보 공개를 방지하기 위한 중요한 메커니즘이다. TLS로 보호된 통신은 [RFC6125]에 따라 검증될 수 있다. 구현 보안 고려사항은 "Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)" [RFC9325]에서 확인할 수 있다.

15.2 토큰 보안

이 절은 비규범적이다.

Bearer 토큰과 디지털 자격 증명은 도난 및 재생 공격에 취약하다. 완화책에는 합리적으로 짧은 수명 사용, 토큰을 특정 대상자에 바인딩하는 것, 토큰을 안전하게 저장하는 것이 포함된다.

15.3 접근 요청 및 허가

이 절은 비규범적이다.

16. 개인정보 보호 고려사항

이 절은 비규범적이다.

데이터 최소화, 사용자 동의 및 개인정보 보호 구현 패턴을 포함한 LWS Protocol의 개인정보 보호 영향.

자격 증명은 사용자와 에이전트에 대한 정보를 포함한다. 디지털 서명은 변조를 방지할 수 있지만, 클라이언트 또는 제3자가 암호화되지 않은 자격 증명 내부의 값을 읽을 가능성이 있다.

그 결과, 자격 증명 발급자는 인증 또는 권한 부여에 필요한 정보만 포함하는 토큰을 만들고, 필요한 경우가 아니라면 민감한 속성을 포함하지 않을 것을 권장한다.

일반적으로 암호화되지 않은 자격 증명 데이터를 로그에 기록하는 것은 안티패턴이다. 이것이 필요한 경우, 구현은 자격 증명의 주체의 개인정보를 보호하기 위해 자격 증명을 잘라내거나 해시할 수 있다.

JWT에서 가명 식별자를 사용하는 경우, 스토리지 서버는 여전히 시간이 지나면서 동일한 에이전트의 요청을 상관시킬 수 있다. 이 경우 사용자 개인정보를 보호하기 위해, 클라이언트 애플리케이션은 각 JWT가 한 번만 사용되는 JWT의 일괄 발급을 요청할 수 있다. 이는 스토리지 서버가 JWT 콘텐츠의 유사성이나 발신 IP 주소와 같은 다른 정보를 사용하여 요청을 상관시키는 것을 방지하지 않는다. 가명 식별자를 사용할 때, 권한 부여 서버는 동일한 식별자를 두 번 이상 발급하지 않도록 주의해야 한다.

16.1 접근 요청 및 허가

이 절은 비규범적이다.

17. IANA 고려사항

이 절은 비규범적이다.

17.1 well-known URI 레지스트리

이 명세는 RFC 5785 [RFC5785]가 설정한 "Well-Known URIs" 레지스트리에 다음 값을 추가한다.

17.2 OAuth 권한 부여 서버 메타데이터 레지스트리

이 명세는 [RFC8414]가 설정한 "OAuth Authorization Server Metadata" 레지스트리에 다음 값을 추가한다.

17.3 application/lws+json 미디어 유형

이 명세는 Linked Web Storage 컨테이너 형식을 준수하는 문서를 식별하기 위해 application/lws+json 미디어 유형을 등록한다.

Linked Web Storage 형식은 JSON-LD 규약을 사용하지만, LWS 구현에는 특정 미디어 유형의 사용을 정당화하는 여러 제약 조건과 추가 요구사항이 있다는 점에 유의하라.

LWS 컨테이너는 JSON-LD의 제한된 프로파일로 간주될 수 있으므로, 구현은 application/ld+json; profile="https://www.w3.org/ns/lws/v1" 미디어 유형을 application/lws+json과 동등한 것으로 간주하는 것이 SHOULD된다.

A. 감사의 말

이 절은 비규범적이다.

이 명세는 Solid Protocol [Solid-Protocol]에서 많은 부분을 가져왔으며, 이 프로토콜은 시간이 지남에 따라 Sarven Capadisli, Tim Berners-Lee, Kjetil Kjernsmo, Ruben Verborgh, Justin Bingham, Dmitri Zagidulin이 편집했다.

B. 참고문헌

B.1 규범적 참고문헌

[FOAF]
FOAF Vocabulary Specification 0.99 (Paddington Edition). Dan Brickley; Libby Miller. FOAF project. 14 January 2014. URL: http://xmlns.com/foaf/spec/
[JSON-LD11]
JSON-LD 1.1. Gregg Kellogg; Pierre-Antoine Champin; Dave Longley. W3C. 16 July 2020. W3C Recommendation. URL: https://www.w3.org/TR/json-ld11/
[ODRL-MODEL]
ODRL Information Model 2.2. Renato Iannella; Serena Villata. W3C. 15 February 2018. W3C Recommendation. URL: https://www.w3.org/TR/odrl-model/
[ODRL-VOCAB]
ODRL Vocabulary & Expression 2.2. Renato Iannella; Michael Steidl; Stuart Myles; Víctor Rodríguez-Doncel. W3C. 15 February 2018. W3C Recommendation. URL: https://www.w3.org/TR/odrl-vocab/
[OPENID-CONNECT-CORE]
OpenID Connect Core 1.0 incorporating errata set 2. N. Sakimura; J. Bradley; M. Jones; B. de Medeiros; C. Mortimore. OpenID Foundation. 15 December 2023. Final. URL: https://openid.net/specs/openid-connect-core-1_0.html
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC3986]
Uniform Resource Identifier (URI): Generic Syntax. T. Berners-Lee; R. Fielding; L. Masinter. IETF. January 2005. Internet Standard. URL: https://www.rfc-editor.org/rfc/rfc3986
[RFC4918]
HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV). L. Dusseault, Ed. IETF. June 2007. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc4918
[RFC5789]
PATCH Method for HTTP. L. Dusseault; J. Snell. IETF. March 2010. Proposed Standard. URL: https://httpwg.org/specs/rfc5789.html
[RFC6585]
Additional HTTP Status Codes. M. Nottingham; R. Fielding. IETF. April 2012. Proposed Standard. URL: https://httpwg.org/specs/rfc6585.html
[RFC6749]
The OAuth 2.0 Authorization Framework. D. Hardt, Ed. IETF. October 2012. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc6749
[RFC6750]
The OAuth 2.0 Authorization Framework: Bearer Token Usage. M. Jones; D. Hardt. IETF. October 2012. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc6750
[RFC7231]
Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content. R. Fielding, Ed.; J. Reschke, Ed. IETF. June 2014. Proposed Standard. URL: https://httpwg.org/specs/rfc7231.html
[RFC7232]
Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests. R. Fielding, Ed.; J. Reschke, Ed. IETF. June 2014. Proposed Standard. URL: https://httpwg.org/specs/rfc7232.html
[RFC7233]
Hypertext Transfer Protocol (HTTP/1.1): Range Requests. R. Fielding, Ed.; Y. Lafon, Ed.; J. Reschke, Ed. IETF. June 2014. Proposed Standard. URL: https://httpwg.org/specs/rfc7233.html
[RFC7240]
Prefer Header for HTTP. J. Snell. IETF. June 2014. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc7240
[RFC7386]
JSON Merge Patch. P. Hoffman; J. Snell. IETF. October 2014. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc7386
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[RFC8288]
Web Linking. M. Nottingham. IETF. October 2017. Proposed Standard. URL: https://httpwg.org/specs/rfc8288.html
[RFC8414]
OAuth 2.0 Authorization Server Metadata. M. Jones; N. Sakimura; J. Bradley. IETF. June 2018. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8414
[RFC8693]
OAuth 2.0 Token Exchange. M. Jones; A. Nadalin; B. Campbell, Ed.; J. Bradley; C. Mortimore. IETF. January 2020. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8693
[RFC9068]
JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens. V. Bertocci. IETF. October 2021. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9068
[RFC9110]
HTTP Semantics. R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed. IETF. June 2022. Internet Standard. URL: https://httpwg.org/specs/rfc9110.html
[rfc9112]
HTTP/1.1. R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed. IETF. June 2022. Internet Standard. URL: https://httpwg.org/specs/rfc9112.html
[RFC9264]
Linkset: Media Types and a Link Relation Type for Link Sets. E. Wilde; H. Van de Sompel. IETF. July 2022. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9264
[RFC9457]
Problem Details for HTTP APIs. M. Nottingham; E. Wilde; S. Dalal. IETF. July 2023. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9457
[URL]
URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/
[WebArch]
Architecture of the World Wide Web, Volume One. Ian Jacobs; Norman Walsh. W3C. 15 December 2004. W3C Recommendation. URL: https://www.w3.org/TR/webarch/
[XMLSCHEMA11-2]
W3C XML Schema Definition Language (XSD) 1.1 Part 2: Datatypes. David Peterson; Sandy Gao; Ashok Malhotra; Michael Sperberg-McQueen; Henry Thompson; Paul V. Biron et al. W3C. 5 April 2012. W3C Recommendation. URL: https://www.w3.org/TR/xmlschema11-2/

B.2 정보성 참고문헌

[LDN]
Linked Data Notifications. Sarven Capadisli; Amy Guy. W3C. 2 May 2017. W3C Recommendation. URL: https://www.w3.org/TR/ldn/
[RFC5785]
Defining Well-Known Uniform Resource Identifiers (URIs). M. Nottingham; E. Hammer-Lahav. IETF. April 2010. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc5785
[RFC6125]
Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS). P. Saint-Andre; J. Hodges. IETF. March 2011. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc6125
[RFC8259]
The JavaScript Object Notation (JSON) Data Interchange Format. T. Bray, Ed. IETF. December 2017. Internet Standard. URL: https://www.rfc-editor.org/rfc/rfc8259
[RFC9325]
Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS). Y. Sheffer; P. Saint-Andre; T. Fossati. IETF. November 2022. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc9325
[RFC9700]
Best Current Practice for OAuth 2.0 Security. T. Lodderstedt; J. Bradley; A. Labunets; D. Fett. IETF. January 2025. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc9700
[Solid-Protocol]
Solid Protocol. Sarven Capadisli; Tim Berners-Lee; Kjetil Kjernsmo. Solid Community Group. 12 May 2024. Draft Community Group Report. URL: https://solidproject.org/TR/protocol