This page contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned on this page are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.
Status Authors Coach DRIs Owning Stage Created
proposed @oelmekki @jpcyiza @tkuah @derekferguson 2023-09-12

ActivityPub 지원

요약

이 제안의 최종 목표는 GitLab에 상호 운용성 기능을 구축하여 한 GitLab 인스턴스에서 다른 인스턴스에 호스팅된 프로젝트로 병합 요청을 열 수 있도록 하고, 모든 의지가있는 인스턴스를 전역 네트워크로 병합하는 것입니다.

이를 달성하기 위해 우리는 Fediverse에서 사용되는 w3c 표준 인 ActivityPub을 사용할 것을 제안합니다. 이를 통해 견고하고 싸움터에서 시험한 프로토콜을 기반으로 구축할 수 있으며 GitLab을 보다 넓은 커뮤니티에 공개할 수 있을 것입니다.

인스턴스간 병합 요청을 시작하기 전에, ActivityPub에 대한 도메인 지식을 구축하고 더 고급 기능을 지원할 아키텍처를 만드는 데 도움이 되는 더 작은 단계부터 시작하고자합니다. 이에 따라 피드버스에서 사람들이 GitLab의 활동을 구독하고, 예를 들어 GitLab에서 호스팅되는 즐겨찾는 프로젝트가 새 릴리스를 만들 때 선택한 소셜 네트워크에서 알림을받을 수있는 소셜 기능을 구현하기로 제안합니다. 이것은 GitLab을 더 소셜하게 만들고 그 수요층을 늘릴 수있는 기회입니다.

관련 기술 및 용어 설명

ActivityPub 및 Fediverse에 대해 이미 알고있는 경우 모티베이션으로 이동해도 좋습니다.

웹의 분산화를 위한 추진 중, 여러 프로젝트가 그들의 이유에 따라 다른 이상을 가진 다양한 프로토콜을 시도했습니다. 몇 가지 예는 다음과 같습니다.

최근 ActivityPub가 확장되었습니다. 그것은 일반적으로 (Fediverse라고도 함)라고 더 잘 알려진 것으로, Mastodon(어떤 종류의 분산형 Facebook으로 설명 될 수있음) 또는 Lemmy (어떤 종류의 분산형 Reddit으로 설명 될 수있음)과 같은 응용 프로그램을 통해 이루어졌습니다.

ActivityPub에는 구현자들에게 매력적으로 만드는 몇 가지 이점이 있습니다.

  • HTTP 위에 구축되었습니다. ActivityPub을 구현하려면 새 소프트웨어를 설치하거나 TCP/UDP를 조작할 필요가 없습니다. 웹 서버(예: rails 애플리케이션과 같은) 또는 HTTP API를 제공하는 응용 프로그램이 있다면 필요한 모든 것이 이미 갖추어져 있습니다.
  • JSON 위에 구축되었습니다. 모든 통신은 기본적으로 JSON 객체이며, 이는 웹 개발자들이 이미 익숙한 것으로 채택을 단순화 합니다.
  • W3C 표준이며 이미 여러 구현이 있습니다. W3C의 시험을 통과한 것은 안정성과 품질에 대한 보증으로, HTML, CSS 또는 다른 웹 표준 작업을 통해 수년 후에 사라지거나 관련성이 없어질까 봐 두려움없이 그들의 작업 위에 구축 할 수 있다는 것을 방해없이 증명해왔습니다.

Fediverse

Mastodon과 Lemmy의 핵심 아이디어는 Fediverse라고합니다. 완전한 분산화 대신, 이러한 어플리케이션은 연합을 기반으로 하며 여전히 서버들과 클라이언트들이 존재합니다. SSB, Dat 및 IPFS와 같은 P2P가 아니라 한 서버들이 단일 엔티티에 의해 제어되는 중앙 서버들이 서로 채팅하는 한 갤럭시에 의존하는 것입니다.

사용자는 이러한 서버 중 하나(인스턴스라고 함)에 가입하고 나서 그들은 이 인스턴스 이거나, 다른 인스턴스에서 사용자와 상호 작용 할 수있다. 사용자의 관점에서, 그들은 글로벌 네트워크에 액세스 할수 있고, 자신의 인스턴스만 보는 것이 아니라 다른 인스턴스에 게시된 기사를 볼 수 있고, 댓글을 남기고 좋아요를 누르거나 기타 등등을 할 수 있습니다.

극복부분: 그들의 인스턴스는 사용자가 회신 할 사용자가 호스팅되어 있는 위치를 알고 있습니다. 사용자가 피드를 구독하면, 그들의 인스턴스는 피드가 호스팅 된 인스턴스에 이 구독을 알립니다.이 대상 인스턴스는 새로운 활동이 생성 될 때 새로운 메시지를 보내게 됩니다. 이것은 RSS와 같이 지속적인 폴 모델이 아니라 푸시 모델을 가능하게 합니다. 물론 방금 설명 한 것은 행복한 경로이며, 길이ennes, 검증 및 결함 허용등이 계속됩니다.

ActivityPub

Fediverse 뒤에는 ActivityPub 프로토콜이 있습니다. 이것은 일반적으로 소셜 네트워크 구현이 가능하며 확장 가능성을 제공하는 HTTP API입니다.

기본 아이디어는 actoractivity를 보내고 받는 것입니다. 활동은 잘 정의 된 속성을 가진 구조화된 JSON 메시지이지만 모든 필요에 대응하도록 확장 할 수 있습니다. 사용자는 네스트 된 JSON 객체이며 전문적인 부분은 W3C 사이트인데 합당한 모델을 가지고 있습니다.

어떤 종류의 액터가 주요인지라도 활동은 사람에 대한 이용 사례이지만, 액터는 반드시 사람에 매핑될 필요가 없습니다. 아무것이나 액터가 될 수 있습니다: 주제, 서브레딧, 그룹, 이벤트. GitLab의 경우, “활동”을 의미하는 GitLab의 의미를 포함한모든 것이 ActivityPub 액터가 될 수있습니다. 이는 프로젝트, 그룹 및 릴리스와 같은 항목을 포함하여 보다 추상적인 예에서 액터를 실행 가능한 피드로 생각할 수 있습니다.

ActivityPub 그 자체로는 Fediverse를 구현하는 데 필요한 모든 것을 다루지 않습니다. 특히 구현자들에 의해 이러한 부분은 해결되어야 하는데:

  • 스팸을 다루는 방법을 찾는 것. 스팸은 다른 인스턴스를 승인하거나 (수신을 중단함으로) 차단하는 것으로 처리됨.
  • 새로운 인스턴스를 발견하는 것.
  • 네트워크 전체에서 검색 수행하기.

동기

소셜 미디어 프로토콜이 GitLab에 유용한 이유는 무엇일까요? 사용자들은 각 호스트에 등록할 필요 없이 다양한 프로젝트 간에 상호 작용할 수 있는 단일 전역 GitLab 네트워크를 원합니다.

이미 매우 인기 있는 토론들이 있었습니다:

이상적인 작업 흐름은 다음과 같습니다:

  1. Alice는 gitlab.example.org와 같은 즐겨 사용하는 GitLab 인스턴스에 등록합니다.
  2. 특정 주제의 프로젝트를 찾아본 후, gitlab.com에 있는 Bob의 프로젝트를 볼 수 있습니다.
  3. Alice는 Fork를 선택하고, gitlab.com/Bob/project.gitgitlab.example.org/Alice/project.git으로 포크됩니다.
  4. 그녀는 편집을 하고 병합 요청을 열면, 그 요청은 Bob의 gitlab.com 프로젝트에 나타납니다.
  5. Alice와 Bob은 각자의 GitLab 인스턴스에서 병합 요청을 토론합니다.
  6. Bob은 추가 커밋을 보낼 수 있으며, 이는 Alice의 인스턴스에서 확인할 수 있습니다.
  7. Bob이 병합 요청을 수락하면, 그의 인스턴스가 Alice의 인스턴스에서 코드를 가져옵니다.

이 프로세스에서 ActivityPub은 다음과 같은 방법으로 도움이 될 것입니다:

  • Bob에게 포크가 발생했음을 알려줍니다.
  • 병합 요청을 Bob에게 보냅니다.
  • Alice와 Bob이 병합 요청에 대해 토론할 수 있도록 합니다.
  • 코드가 병합되었음을 Alice에게 알려줍니다.

특정 구현이 필요한 사례에서 도움이 되지 않습니다:

  • 네트워크 전체 검색 구현.
  • 인스턴스 간 포크 구현. (Git 덕분에 필요하지 않음.)

여기서 왜 ActivityPub을 사용하는 것이 아니라 사용자 정의 방식으로 인스턴스 간 병합 요청을 구현하는 대신 ActivityPub을 사용합니까? 두 가지 이유가 있습니다:

  1. 표준 기반으로 구축함으로써 GitLab을 넘어서 도달하는 것이 도움이 됩니다. 위에서 제시된 작업 흐름은 GitLab만 언급했지만, W3C 표준을 기반으로 빌드하는 것은 다른 벽돌이 그 곳에서 GitLab을 따를 수 있고 코드 공유의 거대한 Fediverse를 구축할 수 있기 때문입니다.
  2. GitLab을 더 사회적으로 만드는 기회. 위의 작업 흐름을 위한 아키텍쳐를 준비하기 위해 더 작은 단계를 거쳐 사람들이 Fediverse 소셜 네트워크에서 활동 피드를 구독할 수 있도록 하여 소셜 네트워크를 구축할 수 있습니다. RSS 피드를 가진 모든 것이 ActivityPub 피드가 될 수 있습니다. Mastodon 사용자는 GitLab의 즐겨찾는 개발자, 프로젝트 또는 주제를 팔로우하고 Mastodon의 피드에서 뉴스를 볼 수 있으며, 이는 GitLab과의 관련성을 높일 것으로 기대됩니다.

목표

  • ActivityPub 기반 소셜 미디어에서 흥미로운 이벤트 공유 가능하게 함
  • 이슈를 열고 한 인스턴스에서 다른 인스턴스로의 토론 가능하게 함
  • 한 인스턴스에서 다른 인스턴스로 프로젝트 포크 가능하게 함
  • 한 인스턴스에서 다른 인스턴스로 병합 요청 열고 토론 및 병합 가능하게 함
  • 네트워크 전체 검색 수행 가능하게 함?

비목표

  • 개인 리소스의 연합
  • 네트워크 전체 검색 수행 가능하게 함?

제안

이 구현 경로의 아이디어는 가장 가치 있는 기능(cross-instance merge requests)에 가장 빠른 경로를 취하는 것이 아니라, 각 반복에서 가장 작지만 유용한 단계를 거쳐 즉시 유용한 기능을 가져올 수 있도록 하는 것입니다.

  1. 소셜 팔로잉을 위해 ActivityPub 구현. 이후 Fediverse에서 GitLab 인스턴스의 활동을 팔로우할 수 있습니다.
    1. ActivityPub을 통해 프로젝트 릴리스를 구독
    2. ActivityPub을 통해 특정 주제의 프로젝트 생성을 구독
    3. ActivityPub을 통해 프로젝트 활동을 구독
    4. ActivityPub을 통해 그룹 활동을 구독
    5. ActivityPub을 통해 사용자 활동을 구독
  2. 서로 다른 인스턴스에서 프로젝트를 포크할 수 있도록 서로 다른 인스턴스에서 프로젝트를 포크
  3. 인스턴스 간 토론을 위해 ActivityPub 구현 서로 다른 인스턴스에서 이슈 및 병합 요청에 대해 토론할 수 있도록
    1. 이슈에서
    2. 병합 요청에서
  4. 인스턴스 간 병합 요청 제출을 위해 ActivityPub 구현 다른 인스턴스에 병합 요청 제출
  5. 서로 다른 인스턴스에서 네트워크 전체 검색 프로젝트를 발견할 수 있도록

마지막 단계가 전부 포함되어야 하는지 논의를 열어볼 수 있습니다. 현재 대부분의 Fediverse 앱에서 인스턴스가 모르는 인스턴스에서 리소스를 표시하려고 할 때(일반적으로 팔로우하려는 사용자), 자신의 인스턴스의 검색 상자에 리소스의 URL을 붙여넣으면 원격 리소스를 가져와 표시하게 됩니다. 먼저 그것을 할 계획입니다.

문제는 다음과 같습니다: 계속해서 그대로 유지할 것인가요? 이 UX에는 심각한 마찰이 있으며, 특히 Fediverse UX 패턴에 익숙하지 않은 사용자에게(아마도 대부분의 GitLab 사용자) 있습니다. 반면, 분산 검색은 충분히 복잡하여 자신만의 청사진을 가치있게 여길만한 문제입니다 (물론 예전처럼 복잡하지는 않지만, 분산화 프로토콜 및 애플리케이션이 한동안 이것에 대해 작업해왔기 때문입니다).

디자인 및 구현 세부 정보

먼저, 사용할 세 가지 표준 사양에 익숙해지는 것이 좋습니다.

  • ActivityPub은 연맹을 구현하는 데 발생하는 HTTP 요청을 정의합니다.
  • ActivityStreams은 프로토콜의 사용자들에 의해 교환되는 JSON 메시지의 형식을 정의합니다.
  • Activity Vocabulary은 기본적으로 인식되는 다양한 메시지를 정의합니다.

문서가 너무 밀집해서 따라가기 힘들다면 언제든지 궁금한 점이나 문의 사항이 있으면 @oelmekki님께 문의해 주세요.

프로덕션 준비 상태

TBC

소셜 팔로우 파트

이 부분은 GitLab에 새로운 ActivityPub 액터를 추가 할 수 있도록 기본 작업을 하는 것입니다.

구현할 5가지 액터는 다음과 같습니다:

  • releases 액터: 특정 프로젝트에서 새 릴리스를 만들 때 알림을 받음
  • topic 액터: 새로운 프로젝트가 주제에 추가될 때 알림을 받음
  • project 액터: 프로젝트의 모든 활동과 관련된 알림
  • group 액터: 그룹의 모든 활동과 관련된 알림
  • user 액터: 사용자의 모든 활동과 관련된 알림

지금은 공개 리소스만 다루고 있습니다. 비공개 리소스의 연맹을 허용하는 것은 나중에 해결할 어려운 문제이며, 그것이 가능하다면 나중에 해결할 것입니다.

엔드포인트

각 액터는 3개의 엔드포인트가 필요합니다:

  • 프로필 엔드포인트: 이름, 설명과 함께 인박스와 아웃박스로의 링크도 포함됩니다.
  • 아웃박스 엔드포인트: 액터의 이전 활동을 표시하는 것을 허용합니다.
  • 인박스 엔드포인트: 팔로우 및 언팔로우 요청을 게시하기 위한 것(우리가 현재 사용하지 않을 다른 여러 기능도 있음).

이러한 엔드포인트를 제공하는 컨트롤러는 app/controllers/activity_pub/에 있습니다. 이 네임스페이스를 사용하여 ActivityPub JSON 응답을 프론트엔드용 응답과 혼동하지 않도록 하려고 결정했으며, 나중에 포맷 활동이 독립 앱, 기타와 우리의 나중에 나올 인스턴스 간 기능을 위해 다른 방식으로 할 수 있기 때문입니다. 또한, 이 네임스페이스를 사용하면 모든 엔드포인트에서 필요한 것을 간편하게 전환할 수 있습니다. 예를 들어, 개인 프로젝트에 액세스할 수 없도록 하는 등.

직렬화기

app/serializers/activity_pub/의 직렬화기는 ActivityStreams 객체의 본질이며, 개발자가 제공한 데이터를 검증하고 공통 필드를 설정하며 페이징을 제공하는 추상 클래스 ActivityPub::ActivityStreamsSerializer가 모든 중대한 작업을 수행합니다.

페이징 부분은 Gitlab::Serializer::Pagination을 통해 오프셋 페이징을 사용합니다. 키셋 페이징도 허용해야 합니다.

구독

자원에 대한 구독은 팔로우 액티비티를 액터 인박스로 게시함으로써 이루어집니다. 팔로우 액티비티를 받으면, 우리는 대신 Accept 또는 Reject 액티비티를 생성해야 합니다, 구독자의 인박스에 전송합니다.

구현의 일반적인 워크플로우는 다음과 같습니다:

  • 팔로우 액티비티가 JSON으로 인코딩된 채 인박스 엔드포인트로 POST 요청이 수행됩니다.
  • 받은 액티비티가 지원되는 유형이 아닌 경우(예: 누군가가 액티비티에 댓글을 달려고 함) 무시합니다. 그 외에는:
  • 구독자의 프로필 URL로 ActivityPub::Subscription을 생성합니다.
  • 구독자의 인박스 URL을 해결하기 위해 작업을 대기열에 넣습니다.
    • 여기에는 구독자 프로필로 HTTP 요청을 수행하여 그들의 인박스 URL(있는 경우 공유 인박스 URL도)을 찾습니다.
    • 해당 URL을 구독 레코드에 저장합니다.
  • 구독 수락 작업을 대기열에 넣습니다.
    • 여기에는 구독자 인박스로 Accept 액티비티를 게시하기 위해 구독자 인박스로 HTTP 요청을 수행합니다.
    • 구독 상태를 :accepted로 업데이트합니다.

ActivityPub::Subscription은 새로운 추상 모델로, 각자의 테이블을 갖는 우리 액터와 관련된 모델이 상속합니다:

  • ActivityPub::ReleasesSubscription, 테이블 activity_pub_releases_subscriptions
  • ActivityPub::TopicSubscription, 테이블 activity_pub_topic_subscriptions
  • ActivityPub::ProjectSubscription, 테이블 activity_pub_project_subscriptions
  • ActivityPub::GroupSubscription, 테이블 activity_pub_group_subscriptions
  • ActivityPub::UserSubscription, 테이블 activity_pub_user_subscriptions

Subscription 모델에서 단일 테이블을 사용하는 대신에 여러 모델 중 하나로 선택한 이유는 모든 모델에 대한 특정 연결 및 유효화(validation)가 필요하기 때문입니다(예를 들어 ActivityPub::ProjectSubscription은 Project에 종속되고, ActivityPub::UserSubscription은 그렇지 않음). 또한, 나중을 위해 확장성을 더 많이 제공합니다.

언팔로우

수신 시 취소 활동을 받으면 이전 팔로우를 언구독합니다. 데이터베이스에서 레코드를 직접 삭제할 수 있으므로 어떤 작업자도 필요하지 않습니다.

활동 발송

배우자에게 관련된 특정 이벤트(어떤 것들인가?)가 발생하면 구독자의 인박스에 활동을 발행하기 위해 이벤트를 대기열에 넣어야 합니다(활동은 배우자의 아웃박스에 표시되는 것과 동일함). 동일한 사람에게 활동을 두 번 보내지 않도록 구독자 목록을 중복 처리해야 합니다. 그러나 팔로우 활동을 수신할 때 모델로부터 고유성 유효성 검사로 더 잘 처리하는 것이 아마도 더 나을 것입니다. 더 중요한 것은 동일한 호스트에 대한 요청을 그룹화해야 합니다. 예를 들어 10명의 사용자가 모두 https://mastodon.social/에 있는 경우, 공유된 인박스에 모든 사용자를 수신자로 추가하여 한 번의 요청을 발행해야 하며 각 사용자별로 개별 요청을 보내면 안 됩니다.

Webfinger

Mastodon은 Webfinger 프로토콜을 구현하도록 인스턴스를 필요로 합니다. 이 프로토콜은 특정한 위치에 endpoint를 추가하여 리소스 이름을 조회하고 원하는 URL로 매핑할 수 있게 해줍니다(기본적으로 검색용으로 사용됨). Mastodon은 배우자 이름을 조회할 때 이를 사용하여 그들의 프로필 URL을 찾습니다. 사실, GitLab은 이미 Doorkeeper를 통해 Webfinger 프로토콜 endpoint를 구현하고 있습니다 (이것이 해당 경로에 매핑되는 동작), GitLab에서 JwksController에 구현되어 있습니다. 여기에서는 어떤 불일치도 없으며 이 컨트롤러를 확장할 수 있습니다. 그러나 Jwks와 더 이상 관련이 없으므로 이 컨트롤러의 이름을 바꿔야 할 것입니다. 하지만, 우리는 사용자뿐만 아니라 사용자와 차별화할 방법이 필요합니다. 예를 들어 사용자 요청과 프로젝트 요청을 구분할 수 있는 방법 중 하나는 접두어를 사용하는 것입니다. 즉, user-<사용자명>, project-<프로젝트명> 등입니다. 이 논평은 실제 구현에 도달했을 때도 더욱이 모든 코드를 구현하고 Webfinger 사양을 깊게 파고들기 전에 멀리서 곰곰히 생각해 볼 문제입니다.

HTTP 서명

Mastodon은 HTTP 서명을 요구합니다. 이것은 주어진 서버를 가장하는 스패머가 시도하지 않도록 하기 위한 다른 표준입니다. 이것은 SSH나 PGP와 같이 개인 키와 공개 키로 구성된 비대칭 암호화입니다. 우리는 요청에 서명을 하는 것과 그것을 검증하는 것 둘 다를 구현해야 할 것입니다. 나중에 GitLab 인스턴스 간에 통신을 하고 싶을 때 상당히 도움이 될 것입니다.

호스트 허용 목록 및 차단 목록

잠재적인 스팸에 대한 GitLab 인스턴스 소유자의 통제를 위해 호스트의 두 상호 배타적인 목록을 관리할 수 있어야 합니다: - 허용 목록: 이 목록에 기재된 호스트만 연합이 가능해야 합니다. - 차단 목록: 모든 호스트가 연합될 수 있고 해당 목록에 기재된 호스트만 불가능해야 합니다.

소유자가 허용 목록과 차단 목록 사이를 전환할 수 있도록 설정이 필요할 것입니다. 처음에는 레일즈 콘솔에서 관리 가능하지만 최종적으로는 관리자 인터페이스에 해당 섹션이 필요할 것입니다.

제한 및 롤아웃

첫 몇 달 동안 기능을 출시할 때 부하를 통제하기 위해 gitlab.com에 대해 허용 목록을 사용하고 Fediverse 서버를 시간당 몇 개씩 롤아웃하여 부하를 점진적으로 확인할 것입니다. 최종적으로 차단 목록으로 전환하기 전에 (참고: 현재 진행 중인 토론에 따르면 gitlab.com에서 연합을 활성화해야 할 것인지 여부에 대한 몇 가지 논의가 있습니다) 연합이 남용되지 않도록 제한을 구현해야 할 것입니다: - 리소스가 받을 수 있는 구독 수의 제한. - 제3자 서버가 생성할 수 있는 구독 수의 제한.

인스턴스 간 이슈 및 병합 요청 부분

ActivityPub을 실무에서 경험한 후에 설계할 것입니다.