서버에 독립적인 ID를 사용하는 이식 가능한 ActivityPub 객체를 정의하는 초안 구현 제안.
서버에 독립적인 ID를 가진 이식 가능한 ActivityPub 객체.
식별자로 HTTP(S) URI를 사용하는 것은 큰 단점이 있습니다. 서버가 사라지면, 그것을 사용하는 모든 사람이 자신의 정체성과 데이터를 잃게 됩니다.
제안된 해결책은 다음 제약 조건을 만족해야 합니다:
Nomadic identity 메커니즘은 정체성을 서버와 독립적으로 만들며, 원래 Zot federation protocol의 일부였습니다.
Streams (2021)는 ActivityStreams 직렬화를 지원하는 Nomad protocol을 통해 유목형 계정을 사용할 수 있게 했습니다.
FEP-c390 (2022)은 ActivityPub과 호환되는 분산 신원 해결책을 도입했습니다. 이는 서버 간 팔로워의 무허가 마이그레이션을 가능하게 했지만, 완전한 데이터 이식성은 제공하지 않았습니다.
이 문서에서 사용되는 핵심 단어 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL"은 RFC-2119에 설명된 대로 해석되어야 합니다.
ActivityPub 객체는 단일 서버에 묶이지 않은 식별자를 사용함으로써 이식 가능하게 만들 수 있습니다. 이 제안은 이러한 속성을 가지며 ActivityPub 명세와 호환되는 새로운 식별자 유형을 설명합니다.
'ap' URI는 RFC-3986 명세에 따라 구성되지만, authority 위치에는 분산 식별자가 들어갑니다:
ap://did:example:abcdef/path/to/object?name=value#fragment-id
\_/ \________________/ \____________/ \________/ \_________/
| | | | |
scheme authority path query fragment
ap 또는 ap+ef61이어야 합니다. ap scheme 사용을 권장합니다.[!WARNING] authority 구성요소의 예약 문자가 퍼센트 인코딩되지 않은 경우, 'ap' URI는 유효한 RFC-3986 URI가 아닙니다. 그럼에도 불구하고 이 형식이 정규형으로 간주됩니다.
[!WARNING] 이 식별자들은 모든 ActivityPub 객체가 아니라 이식 가능한 객체에만 사용되도록 의도되었기 때문에, 권장 URI scheme은 이 문서의 향후 버전에서
ap+ef61으로 변경될 수 있습니다.
[!NOTE] ActivityPub 명세는 식별자가 그 "원래 서버에 속하는" authority를 가져야 한다고 요구합니다. 'ap' URI의 authority는 DID이며, 이는 특정 서버에 속하지 않습니다.
두 'ap' URI는 정규형이 동일할 때 동등합니다.
정규형 'ap' URI를 생성하려면 다음 작업을 수행해야 합니다:
ap+ef61이면 ap로 바꿉니다.구현체는 did:key 메서드를 지원해야 합니다. 다른 DID 메서드는 상호운용성을 저해할 수 있으므로 사용하지 않아야 합니다.
[!NOTE] 다음 추가 DID 메서드들이 검토되고 있습니다: did:web, did:dns, did:webvh (이전 이름
did:tdw) 및 did:fedi.
DID 문서는 Controlled Identifiers 명세에 정의된 Multikey 유형의 verification method로 표현된 Ed25519 공개 키를 포함해야 합니다.
'ap' URI로 작업할 때는 DID 메서드의 모든 DID URL 기능을 무시해야 합니다.
did:key 식별자는 명세에서 base58-btc와 base64url 둘 다 허용하더라도, 반드시 base58-btc 알파벳을 사용해 생성해야 합니다. 실제로 두 알파벳을 모두 사용하면 서로 다르게 인코딩된 authority를 가진 두 'ap' URI가 동일한 리소스를 가리킨다는 사실을 애플리케이션이 인식하지 못할 수 있습니다.
이식 가능한 객체의 예:
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/data-integrity/v1",
"https://w3id.org/fep/ef61"
],
"type": "Note",
"id": "ap://did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2/objects/dc505858-08ec-4a80-81dd-e6670fd8c55f",
"attributedTo": "ap://did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2/actor?gateways=https%3A%2F%2Fserver1.example,https%3A%2F%2Fserver2.example",
"inReplyTo": "ap://did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK/objects/f66a006b-fe66-4ca6-9a4c-b292e33712ec",
"content": "Hello!",
"attachment": [
{
"type": "Image",
"url": "hl:zQmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n",
"mediaType": "image/png",
"digestMultibase": "zQmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n"
}
],
"to": [
"ap://did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK/actor"
],
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-jcs-2022",
"created": "2023-02-24T23:36:38Z",
"verificationMethod": "did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2#z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2",
"proofPurpose": "assertionMethod",
"proofValue": "..."
}
}
'ap' URI를 역참조하려면, 클라이언트는 well-known 위치 /.well-known/apgateway의 gateway endpoint로 HTTP GET 요청을 보내야 합니다. URI에서 ap:// 접두사를 제거하고 나머지를 gateway URI에 이어 붙여야 합니다. 클라이언트는 application/ld+json; profile="https://www.w3.org/ns/activitystreams" 미디어 타입을 가진 Accept 헤더를 지정해야 합니다.
gateway 요청 예시:
GET https://social.example/.well-known/apgateway/did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2/path/to/object
'ap' URI로 식별되는 ActivityPub 객체는 여러 서버에 동시에 저장될 수 있습니다.
'ap' URI로 식별되는 객체가 서버에 저장되어 있다면, 서버는 요청된 객체를 포함한 상태 200 OK 응답을 반환해야 합니다. Content-Type 헤더의 값은 반드시 application/ld+json; profile="https://www.w3.org/ns/activitystreams"이어야 합니다.
'ap' URI로 식별되는 객체가 서버에 저장되어 있지 않다면, 반드시 404 Not Found를 반환해야 합니다.
객체가 공개되지 않은 경우, 요청이 객체의 의도된 수신자에 속한 actor에 의해 서명되지 않았다면 서버는 이를 제공해서는 안 됩니다.
이식 가능한 객체를 다룰 때, 서버는 'ap' URI를 불투명한 식별자(semantic routing)로 취급해야 합니다.
[!NOTE] 이 문서는 HTTP 전송을 사용하는 웹 gateway를 설명합니다. 그러나 데이터 모델과 인증 메커니즘은 전송 방식에 독립적이며, 다른 유형의 gateway도 존재할 수 있습니다.
인증과 권한 부여는 FEP-fe34 origin 기반 보안 모델에 따라 수행되지만, 두 가지 중요한 차이점이 있습니다:
'ap' URI의 origin은 그 정규형의 authority 구성요소와 동일합니다. 즉, 퍼센트 인코딩이 없는 DID입니다.
DID URL의 origin은 그 did 구성요소와 동일합니다.
'ap' URI로 식별되는 actor, activity, object는 반드시 FEP-8b32 무결성 증명을 포함해야 합니다. 'ap' URI로 식별되는 collection은 무결성 증명을 포함할 수 있습니다. collection에 무결성 증명이 없다면, 다른 인증 방법을 사용해야 합니다.
증명의 verificationMethod 속성 값은 DID URL이어야 하며, 그 DID는 객체의 정규형 식별자의 authority 구성요소와 일치해야 합니다.
[!NOTE] 이 문서는 FEP-2277에 제시된 분류에 따라 "actor", "activity", "collection", "object"라는 용어를 사용합니다.
이식 가능한 객체를 보호하는 데 사용되는 비밀 키를 관리하는 방법은 여러 가지가 있습니다:
하나의 DID subject는 여러 actor를 제어할 수 있습니다(이들은 'ap' URI의 path 구성요소로 구분됩니다).
'ap' URI로 식별되는 actor 객체는 최신 버전의 해당 actor 객체를 가져올 수 있는 gateway의 순서 있는 목록을 담은 gateways 속성을 반드시 가져야 합니다. 목록의 각 항목은 path, query, fragment 구성요소가 비어 있는 HTTP(S) URI여야 합니다. 목록에는 최소 하나의 항목이 있어야 합니다.
gateway는 DID authority 아래의 모든 actor에 대해 동일할 것으로 예상되며, services로 DID 문서에 명시될 수도 있습니다.
예시:
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/data-integrity/v1",
"https://w3id.org/fep/ef61"
],
"type": "Person",
"id": "ap://did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2/actor",
"inbox": "ap://did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2/actor/inbox",
"outbox": "ap://did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2/actor/outbox",
"gateways": [
"https://server1.example",
"https://server2.example"
],
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-jcs-2022",
"created": "2023-02-24T23:36:38Z",
"verificationMethod": "did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2#z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2",
"proofPurpose": "assertionMethod",
"proofValue": "..."
}
}
다른 actor에 대한 참조를 포함하는 ActivityPub 객체를 구성할 때, 구현체는 지정된 actor 객체를 가져올 수 있는 gateway 목록을 제공해야 합니다. 이 목록은 gateways query 매개변수를 사용해 제공할 수 있습니다. 각 gateway 주소는 URI 인코딩되어야 하며, 여러 주소가 있을 경우 쉼표로 구분해야 합니다.
예시:
ap://did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2/actor?gateways=https%3A%2F%2Fserver1.example,https%3A%2F%2Fserver2.example
이 URI는 객체를 두 개의 gateway에서 가져올 수 있음을 나타냅니다:
https://server1.examplehttps://server2.example[!IMPORTANT] 'ap' URI를 비교할 때는 query 매개변수를 버리고 정규형 URI를 사용합니다.
이식 가능한 inbox와 outbox는 ActivityPub 명세에 설명된 대로 동작합니다. 이 endpoint들은 actor가 사용하는 gateway 간에 activity를 동기화하는 데에도 사용됩니다.
actor 객체의 gateways 속성에 명시된 서버는 그 inbox collection을 대상으로 하는 POST 요청을 반드시 받아들여야 합니다.
예시:
POST https://social.example/.well-known/apgateway/did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2/actor/inbox
inbox로 전달되는 activity는 이식 가능하지 않을 수도 있습니다. 서버가 actor를 대신한 전달을 받지 않는다면, 반드시 404 Not Found를 반환해야 합니다.
actor의 inbox에서 activity를 수신하면, 서버는 actor의 데이터가 저장된 다른 서버들에 있는 inbox로 이를 전달해야 합니다. 하나의 activity는 inbox에서 두 번 이상 전달되어서는 안 됩니다.
actor 객체의 gateways 속성에 명시된 서버는 그 outbox collection을 대상으로 하는 POST 요청을 받아들일 수 있습니다. 이러한 서버는 반드시 FEP-ae97을 구현해야 합니다.
outbox로 전달되는 activity는 이식 가능한 actor에 의해 수행되므로, 반드시 그 자체로도 이식 가능해야 합니다. 서버는 이를 인증과 권한 부여 절에 설명된 대로 검증한 다음, FEP-ae97에 설명된 대로 처리해야 합니다. 클라이언트는 서로 다른 서버에 위치한 여러 outbox로 activity를 전달할 수 있습니다.
actor의 outbox에서 activity를 수신하면, 서버는 actor의 데이터가 저장된 다른 서버들에 있는 outbox로 이를 전달해야 합니다. 하나의 activity는 outbox에서 두 번 이상 전달되어서는 안 됩니다.
'ap' URI로 식별되는 collection(inbox 및 outbox collection 포함)은 FEP-8b32 무결성 증명 없이 제공될 수 있습니다. 이를 소비하는 구현체는, portable actor에 귀속된 보안되지 않은 collection이 actor 문서의 gateways 배열에 나열되지 않은 서버에서 가져온 것이라면 이를 처리해서는 안 됩니다.
이식 가능한 collection은 비이식형 collection과 동일한 방식으로 필터링 및 페이지네이션할 수 있습니다. gateway는 FEP-ae97 클라이언트가 생성한 collection의 view를 생성할 때 무결성 증명을 제거해야 합니다.
외부 리소스의 무결성은 digest로 증명됩니다. 이식 가능한 객체가 외부 리소스(예: 이미지)에 대한 참조를 포함하는 경우, 해당 리소스의 무결성 digest를 나타내는 digestMultibase 속성도 반드시 포함해야 합니다. digest는 반드시 SHA-256 알고리즘을 사용해 계산해야 합니다.
외부 리소스의 URI는 hashlink여야 합니다.
Image 첨부의 예:
{
"type": "Image",
"url": "hl:zQmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n",
"mediaType": "image/png",
"digestMultibase": "zQmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n"
}
리소스를 가져온 후, 클라이언트는 digest를 계산하고 그 결과를 digestMultibase 속성에 인코딩된 값과 비교함으로써 반드시 무결성을 검증해야 합니다.
hashlink를 사용해 이식 가능한 객체에 첨부된 리소스는 gateway가 저장할 수 있습니다. gateway에서 리소스를 가져오려면, 클라이언트는 well-known 위치 /.well-known/apgateway의 gateway endpoint로 HTTP GET 요청을 보내야 합니다. hashlink URI의 값은 gateway 기본 URI에 이어 붙여야 합니다.
요청 예시:
GET https://social.example/.well-known/apgateway/hl:zQmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n
'ap' URI는 기존 ActivityPub 구현체와 호환되지 않을 수 있습니다. 하위 호환성을 제공하기 위해, 객체의 정규형 식별자 대신 gateway 기반 HTTP(S) URI를 사용할 수 있습니다:
https://social.example/.well-known/apgateway/did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2/path/to/object
게시자는 호환 식별자를 구성할 때 actor의 gateways 목록에서 첫 번째 gateway를 반드시 사용해야 합니다. 'ap' URI를 지원하는 소비 구현체는 did: 앞의 URI 부분을 제거하고 정규형 식별자를 다시 구성해야 합니다. 정규형 식별자는 같지만 서로 다른 gateway에 위치한 객체는 같은 객체의 서로 다른 인스턴스로 취급해야 합니다.
호환 식별자를 사용하는 경우, 게시자는 객체 ID에 gateways query 매개변수를 추가해서는 안 됩니다.
다른 서버와 통신하기 위해 HTTP signature가 필요한 경우, actor를 대신해 요청을 보내는 각 gateway는 별도의 비밀 키를 사용해야 합니다. 해당 공개 키는 FEP-521a에 설명된 대로 assertionMethod 속성을 사용해 actor 문서에 추가되어야 합니다.
[!WARNING] 호환 식별자를 사용하는 경우, 동일한 gateway가 제공하는 객체들은 'ap' URI를 지원하지 않는 구현체에는 같은 origin을 가진 것으로 보일 것입니다.
이식 가능한 actor의 WebFinger 주소는 ActivityPub and WebFinger 보고서의 2.2절에 설명된 역발견 알고리즘으로 얻을 수 있지만, 식별자에서 호스트명을 가져오는 대신 actor의 gateways 배열 첫 번째 gateway에서 가져와야 합니다.
(이 절은 규범적이지 않습니다.)
gateways 배열은 path 구성요소를 가진 HTTP(S) URI를 포함할 수 있으며, 이로써 well-known 위치에 기반한 발견과 달리 "follow your nose" 원칙에 기반한 발견이 가능해집니다.
gateway endpoint가 https://social.example/ap인 경우의 호환 객체 ID 예시:
https://social.example/ap/did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2/path/to/object
gateways 속성의 대안이 제안은 gateways 속성을 사용하지만, 다음 대안들도 검토되고 있습니다:
endpoints 매핑 안의 gateways 속성aliases 및 sameAs (객체의 HTTP(S) URI 포함)alsoKnownAs (계정 마이그레이션에 사용되므로, 이 속성의 사용은 문제를 일으킬 수 있음)url (alternate relation type 사용)actor 문서에 gateway를 명시하는 대신, DID 문서에서 DID services를 사용해 명시할 수 있습니다. 이 접근법은 did:key 같은 생성형 DID 메서드와는 호환되지 않으며, 그러한 메서드는 일부 유형의 애플리케이션에 필요할 수 있습니다.
hashlink로 미디어를 참조하는 제안된 접근법은 접근 제어를 지원하지 않습니다. 해시를 아는 누구나 파일을 가져올 수 있습니다.
이 제한을 우회하기 위해, digest를 상위 문서의 ap:// 식별자와 결합한 다른 종류의 식별자를 사용할 수 있습니다. gateway는 상위 문서 ID가 제공되지 않으면 미디어를 제공하지 않으며, 요청 서명자가 문서를 볼 권한이 있는지, 따라서 첨부된 미디어도 볼 권한이 있는지를 확인할 것입니다.
CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
법이 허용하는 범위 내에서, 이 Fediverse Enhancement Proposal의 저자들은 이 작업에 대한 모든 저작권 및 관련 또는 인접 권리를 포기했습니다.