Skip to content

feat(api): add clean-slate v1 backend for docker-git control#88

Merged
skulidropek merged 10 commits intoProverCoderAI:mainfrom
skulidropek:issue-84
Mar 5, 2026
Merged

feat(api): add clean-slate v1 backend for docker-git control#88
skulidropek merged 10 commits intoProverCoderAI:mainfrom
skulidropek:issue-84

Conversation

@skulidropek
Copy link
Copy Markdown
Member

@skulidropek skulidropek commented Feb 21, 2026

Summary

  • add new workspace package packages/api with clean-slate v1 HTTP backend on Effect Platform
  • implement project lifecycle API (create/delete/up/down/recreate/ps/logs) without CLI dependency
  • implement full agent lifecycle API (start/list/get/stop/attach/logs) with in-memory registry + snapshot restore
  • add project SSE stream endpoint for deployment and agent events (/v1/projects/:projectId/events)
  • add root scripts for api build/dev/start/test/typecheck and docs for running the new module

API Endpoints

  • GET /v1/health
  • GET /v1/projects
  • GET /v1/projects/:projectId
  • POST /v1/projects
  • DELETE /v1/projects/:projectId
  • POST /v1/projects/:projectId/up
  • POST /v1/projects/:projectId/down
  • POST /v1/projects/:projectId/recreate
  • GET /v1/projects/:projectId/ps
  • GET /v1/projects/:projectId/logs
  • GET /v1/projects/:projectId/events (SSE)
  • POST /v1/projects/:projectId/agents
  • GET /v1/projects/:projectId/agents
  • GET /v1/projects/:projectId/agents/:agentId
  • GET /v1/projects/:projectId/agents/:agentId/attach
  • POST /v1/projects/:projectId/agents/:agentId/stop
  • GET /v1/projects/:projectId/agents/:agentId/logs

Validation

  • pnpm -C /home/dev/workspaces/provercoderai/docker-git/issue-84 run api:typecheck
  • pnpm -C /home/dev/workspaces/provercoderai/docker-git/issue-84 run api:test
  • pnpm -C /home/dev/workspaces/provercoderai/docker-git/issue-84 run api:build
  • smoke check: GET /v1/health returns {"ok":true}

Closes #84

@skulidropek
Copy link
Copy Markdown
Member Author

Konrad Geletey, [22 Feb 2026 10:24:33]
А сможешь на вход поддержать:
https://forgefed.org/spec/#issues

Konrad Geletey, [22 Feb 2026 10:27:30]
И добавить поддержку follow, чтобы можно было подписатся на отдачу задач https://www.w3.org/TR/activitypub/
image Ты хочешь что бы такое API было?

@skulidropek
Copy link
Copy Markdown
Member Author

Proof for Konrad request (ForgeFed issues input + ActivityPub follow)

Implemented in commit: 984ce9cd53f6da3eb2e9ca3d14890a33c422971d

What was requested:

Verified via live curl run against API:

  1. Create Follow activity
curl -sS -X POST http://127.0.0.1:3366/v1/federation/follows \
  -H 'content-type: application/json' \
  -d '{"actor":"https://dev.example/users/bot","object":"https://tracker.example/issues/followers","capability":"https://tracker.example/caps/follow"}'

Observed: status=pending, activity.type=Follow

  1. Accept follow through inbox
curl -sS -X POST http://127.0.0.1:3366/v1/federation/inbox \
  -H 'content-type: application/json' \
  -d '{"type":"Accept","object":"urn:docker-git:activity:follow:..."}'

Observed: result.kind=follow.accept, subscription status switched to accepted

  1. Ingest ForgeFed Offer(Ticket)
curl -sS -X POST http://127.0.0.1:3366/v1/federation/inbox \
  -H 'content-type: application/json' \
  -d '{"@context":["https://www.w3.org/ns/activitystreams","https://forgefed.org/ns"],"id":"https://tracker.example/offers/42","type":"Offer","target":"https://tracker.example/issues","object":{"type":"Ticket","id":"https://tracker.example/issues/42","attributedTo":"https://origin.example/users/alice","summary":"Title","content":"Body"}}'

Observed: result.kind=issue.offer

  1. Query persisted state
curl -sS http://127.0.0.1:3366/v1/federation/follows
curl -sS http://127.0.0.1:3366/v1/federation/issues

Observed:

  • follows: 1, first item status accepted
  • issues: 1, first item status offered

Also verified locally before push:

  • pnpm run api:typecheck
  • pnpm run api:build
  • pnpm run api:test
  • pnpm --filter ./packages/api lint

Changed files:

  • packages/api/src/services/federation.ts
  • packages/api/src/http.ts
  • packages/api/src/api/contracts.ts
  • packages/api/src/api/schema.ts
  • packages/api/tests/federation.test.ts
  • packages/api/tests/schema.test.ts
  • packages/api/README.md

@skulidropek
Copy link
Copy Markdown
Member Author

Анализ изображения из PR (пример ActivityPub Person с inbox/outbox/followers/following/liked)

Проверил live через curl на локально поднятом API (http://127.0.0.1:3334).

Что подтверждено и уже работает:

  1. ForgeFed issues intake через inbox
curl -sS -X POST http://127.0.0.1:3334/v1/federation/inbox \
  -H 'content-type: application/json' \
  -d '{"@context":["https://www.w3.org/ns/activitystreams","https://forgefed.org/ns"],"id":"https://tracker.example/offers/42","type":"Offer","target":"https://tracker.example/issues","object":{"type":"Ticket","id":"https://tracker.example/issues/42","attributedTo":"https://origin.example/users/alice","summary":"Need reproducible CI parity","content":"Implement API behavior matching CLI."}}'

Факт: result.kind = "issue.offer", issue сохраняется в GET /v1/federation/issues.

  1. ActivityPub Follow flow (создание + Accept)
curl -sS -X POST http://127.0.0.1:3334/v1/federation/follows \
  -H 'content-type: application/json' \
  -d '{"actor":"https://dev.example/users/bot","object":"https://tracker.example/issues/followers","capability":"https://tracker.example/caps/follow"}'

curl -sS -X POST http://127.0.0.1:3334/v1/federation/inbox \
  -H 'content-type: application/json' \
  -d '{"type":"Accept","object":"urn:docker-git:activity:follow:<id>"}'

Факт: статус подписки переходит pending -> accepted, подтверждается GET /v1/federation/follows.

Что НЕ реализовано относительно изображения (Person API shape):

  • Нет отдельного actor document endpoint с полями:
    • type: "Person"
    • inbox, outbox, followers, following, liked
  • Нет отдельных коллекций followers/following/liked в activitypub-форме.

Проверка:

curl -i http://127.0.0.1:3334/v1/federation/actor

Факт: HTTP 404.

Итог:

  • Требование Konrad из текста по issues intake + follow выполнено.
  • Если нужно 1:1 соответствие именно API-форме со скрина (Person + linked collections), это отдельная доработка поверх текущей реализации.

@kogeletey
Copy link
Copy Markdown

curl -sS -X POST http://127.0.0.1:3334/v1/federation/follows
-H 'content-type: application/json'
-d '{"actor":"https://dev.example/users/bot","object":"https://tracker.example/issues/followers","capability":"https://tracker.example/caps/follow"}'

curl -sS -X POST http://127.0.0.1:3334/v1/federation/inbox
-H 'content-type: application/json'
-d '{"type":"Accept","object":"urn:docker-git:activity:follow:"}'

Эти обьекты не правильные + example точно заменяется на домен который указывается?

@skulidropek
Copy link
Copy Markdown
Member Author

Сделал правки по замечанию Konrad: "объекты не правильные" и "заменяется ли .example на указанный домен".

Коммит: f1bba4d3b47f48d18efe6319f5dc83b07d85bf5d

Что изменено:

  • Добавлены ActivityPub endpoints с формой Person и collections:
    • GET /v1/federation/actor
    • GET /v1/federation/outbox
    • GET /v1/federation/followers
    • GET /v1/federation/following
    • GET /v1/federation/liked
  • POST /v1/federation/follows теперь:
    • генерирует URL-based activity id (не urn)
    • поддерживает domain в body (или DOCKER_GIT_FEDERATION_PUBLIC_ORIGIN)
    • заменяет .example хосты в actor/object/inbox на указанный домен
    • использует локальный actor по умолчанию: <origin>/v1/federation/actor

Proof (live curl):

  1. Actor document (Person)
curl -sS http://127.0.0.1:3334/v1/federation/actor \
  -H 'x-forwarded-proto: https' \
  -H 'x-forwarded-host: social.provercoder.ai'

Observed:

  • type = "Person"
  • id = "https://social.provercoder.ai/v1/federation/actor"
  • inbox/outbox/followers/following/liked все на https://social.provercoder.ai/...
  1. Follow with .example replacement by domain
curl -sS -X POST http://127.0.0.1:3334/v1/federation/follows \
  -H 'content-type: application/json' \
  -d '{"domain":"https://social.provercoder.ai","actor":"https://dev.example/users/bot","object":"https://tracker.example/issues/followers","capability":"https://tracker.example/caps/follow"}'

Observed:

  • activity.id = "https://social.provercoder.ai/v1/federation/activities/follows/<uuid>"
  • activity.actor = "https://social.provercoder.ai/users/bot"
  • activity.object = "https://social.provercoder.ai/issues/followers"
  1. Accept + following/outbox
curl -sS -X POST http://127.0.0.1:3334/v1/federation/inbox \
  -H 'content-type: application/json' \
  -d '{"type":"Accept","object":"<activity.id>"}'

curl -sS http://127.0.0.1:3334/v1/federation/following \
  -H 'x-forwarded-proto: https' \
  -H 'x-forwarded-host: social.provercoder.ai'

curl -sS http://127.0.0.1:3334/v1/federation/outbox \
  -H 'x-forwarded-proto: https' \
  -H 'x-forwarded-host: social.provercoder.ai'

Observed:

  • inbox result: kind = "follow.accept"
  • following: type = "OrderedCollection", totalItems = 1
  • outbox: type = "OrderedCollection", содержит созданную Follow activity

Локальная верификация:

  • pnpm --filter ./packages/api lint
  • pnpm --filter ./packages/api typecheck
  • pnpm --filter ./packages/api test
  • pnpm run api:build
  • pnpm run lint
  • pnpm run check

@skulidropek
Copy link
Copy Markdown
Member Author

@kogeletey привет.

В ветке issue-84 добавили правки по твоему комментарию:

  • корректный ActivityPub Person endpoint (/v1/federation/actor) с inbox/outbox/followers/following/liked
  • коллекции outbox/followers/following/liked
  • в follow добавили поддержку domain и замену .example на указанный домен
  • Follow activity id теперь URL-based (не urn)

Пожалуйста, посмотри: это то, что ты хотел получить?
Если нужно, могу сразу подправить формат/поля под твой точный target.

@kogeletey
Copy link
Copy Markdown

Убери версионирование api пожалуйста

@skulidropek
Copy link
Copy Markdown
Member Author

@kogeletey сделал: убрал версионирование API (/v1).

Теперь маршруты без префикса:

  • GET /health
  • GET /projects
  • POST /projects
  • GET /federation/actor
  • POST /federation/follows
  • POST /federation/inbox
  • и т.д. (все projects/*, federation/*)

Короткий proof curl:

curl -sS http://127.0.0.1:3334/health
curl -sS http://127.0.0.1:3334/projects
curl -sS http://127.0.0.1:3334/federation/actor

Старый versioned путь теперь не используется:

curl -i http://127.0.0.1:3334/v1/health
# HTTP/1.1 404

Коммит с изменением: 124e860d40f61457ac8a0908da1283602a528407

@skulidropek
Copy link
Copy Markdown
Member Author

@kogeletey привет.

Сделали все пункты из твоих комментариев:

  • ForgeFed issues intake (POST /federation/inbox)
  • ActivityPub follow (POST /federation/follows + Accept через inbox)
  • Person endpoint (GET /federation/actor) с inbox/outbox/followers/following/liked
  • убрали версионирование API (/v1 больше не используется)

Текущие proof-артефакты:

  • код в ветке issue-84 (HEAD 124e860)
  • CI green (run 22344019627)
  • curl-доказательства в комментариях выше

Можешь, пожалуйста, подтвердить, что это финально соответствует тому, что ты хотел?
Если нет — напиши точный diff по формату/полям, сразу поправим.

@kogeletey
Copy link
Copy Markdown

Надо тестировать и запускать

@Payel-git-ol
Copy link
Copy Markdown
Contributor

  1. Не собирается docker
    /usr/bin/env: 'bash\r': No such file or directory
    /usr/bin/env: use -[v]S to pass options in shebang lines
  2. Сделай отдельно docker для api и прокидывай порты для api
  3. Обнови README.md и расписать как выглядит workflow подписки на этот сервис + примеры json

@skulidropek skulidropek merged commit f1e7721 into ProverCoderAI:main Mar 5, 2026
12 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.

Реализовать возможность взаимодействовать без CLI а по API

3 participants