Skip to content

Add ForgeFed exchange federation#234

Merged
skulidropek merged 1 commit intomainfrom
issue-233
May 3, 2026
Merged

Add ForgeFed exchange federation#234
skulidropek merged 1 commit intomainfrom
issue-233

Conversation

@skulidropek
Copy link
Copy Markdown
Member

Что сделано

Closes #233.

Добавлена поддержка ActivityPub / ForgeFed exchange workflow для docker-git API:

  • публичный ActivityPub actor теперь отдает publicKey и application/activity+json;
  • API умеет подписываться на exchange actor через signed Follow;
  • поддержаны targets вида https://exchange.lefine.pro, actor URL и code@exchange.lefine.pro;
  • состояние federation сохраняется в .docker-git/.orch/state/federation.json;
  • remote outbox polling принимает Create(Ticket), дедуплицирует items и сохраняет задачи;
  • для новых Ticket можно автоматически создать docker-git project, запустить agent и отправить Update обратно в remote inbox;
  • добавлены HTTP endpoints, schemas, contracts, env в compose и тесты.

Как пользоваться

1. Поднять API с публичным ActivityPub origin

Если API доступен локально на 127.0.0.1:3334, поднимите Cloudflare tunnel:

cloudflared tunnel --url http://127.0.0.1:3334

Возьмите выданный URL, например:

PUBLIC_ORIGIN="https://example.trycloudflare.com"

Перезапустите API с публичным origin. Для docker compose:

DOCKER_GIT_FEDERATION_PUBLIC_ORIGIN="$PUBLIC_ORIGIN" \
DOCKER_GIT_EXCHANGE_PROJECT_REPO_URL="https://github.com/ProverCoderAI/docker-git" \
DOCKER_GIT_EXCHANGE_AGENT_PROVIDER="codex" \
DOCKER_GIT_OUTBOX_POLLING_INTERVAL_MS="5000" \
docker compose up -d --build api

Можно включить автоподписку на старте:

DOCKER_GIT_FEDERATION_PUBLIC_ORIGIN="$PUBLIC_ORIGIN" \
DOCKER_GIT_EXCHANGE_TARGETS="https://exchange.lefine.pro" \
DOCKER_GIT_EXCHANGE_PROJECT_REPO_URL="https://github.com/ProverCoderAI/docker-git" \
DOCKER_GIT_EXCHANGE_AGENT_PROVIDER="codex" \
docker compose up -d --build api

2. Проверить публичный actor

curl -fsS \
  -H "Accept: application/activity+json" \
  "$PUBLIC_ORIGIN/federation/actor"

В ответе должны быть публичные URL вида $PUBLIC_ORIGIN/federation/inbox, $PUBLIC_ORIGIN/federation/outbox и publicKey.

3. Подписаться на exchange вручную

curl -fsS -X POST "$PUBLIC_ORIGIN/federation/exchange/subscriptions" \
  -H "Content-Type: application/json" \
  --data '{
    "domain":"'"$PUBLIC_ORIGIN"'",
    "target":"https://exchange.lefine.pro",
    "projectRepoUrl":"https://github.com/ProverCoderAI/docker-git",
    "agentProvider":"codex"
  }'

Допустимые target варианты:

https://exchange.lefine.pro
https://exchange.lefine.pro/actor/code
code@exchange.lefine.pro

4. Проверить статус подписки

curl -fsS "$PUBLIC_ORIGIN/federation/exchange/subscriptions"

Ожидаемый результат после ответа exchange: status: "accepted", remoteOutbox: "https://exchange.lefine.pro/outbox/code".

5. Poll remote outbox

Poll без запуска agent, только ingest/dedupe:

curl -fsS -X POST "$PUBLIC_ORIGIN/federation/exchange/poll" \
  -H "Content-Type: application/json" \
  --data '{"runTasks":false}'

Poll с запуском задач:

curl -fsS -X POST "$PUBLIC_ORIGIN/federation/exchange/poll" \
  -H "Content-Type: application/json" \
  --data '{}'

Poll конкретной queue/target:

curl -fsS -X POST "$PUBLIC_ORIGIN/federation/exchange/poll" \
  -H "Content-Type: application/json" \
  --data '{"target":"code"}'

6. Смотреть принятые задачи

curl -fsS "$PUBLIC_ORIGIN/federation/issues"

Статусы задач:

accepted -> queued -> running -> completed
accepted -> queued -> running -> failed

Если Ticket не содержит GitHub URL, API использует projectRepoUrl из подписки или DOCKER_GIT_EXCHANGE_PROJECT_REPO_URL. Без fallback repo задача будет помечена failed.

7. Проверить inbox вручную

Пример локального Create(Ticket) payload:

curl -fsS -X POST "$PUBLIC_ORIGIN/federation/inbox" \
  -H "Content-Type: application/activity+json" \
  --data '{
    "@context":["https://www.w3.org/ns/activitystreams","https://forgefed.org/ns"],
    "id":"https://example.test/outbox/1",
    "type":"Create",
    "actor":"https://example.test/actor/code",
    "object":{
      "type":"Ticket",
      "id":"https://example.test/orders/1",
      "attributedTo":"https://example.test/actor/code",
      "summary":"Test docker-git exchange task",
      "content":"Run a small verification task for https://github.com/ProverCoderAI/docker-git",
      "source":{
        "content":"Run a small verification task for https://github.com/ProverCoderAI/docker-git",
        "mediaType":"text/plain"
      }
    }
  }'

Verification

git diff --check
bun run --filter @effect-template/api lint
bun run api:typecheck
bun run api:test

bun run api:test: 13 test files, 71 tests passed.

@skulidropek skulidropek merged commit 1887717 into main May 3, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Можешь реализовать вот такое API?

1 participant