1
0
Fork
You've already forked server
0

WIP: Refactor old ActivityPub library #1

Draft
lukasmatt wants to merge 14 commits from goap_migration_decouple into master
pull from: goap_migration_decouple
merge into: socialtap:master
socialtap:master

Codebase Analysis

Current Architecture (go-fed/apcore)

Here's the dependency map:

main.go
 └── activity/application.go ← implements app.Application, S2SApplication, C2SApplication
 ├── activity/federation_follow.go ← S2S Follow callback
 ├── handlers/ ← HTTP handlers (inbox, outbox, user, etc.)
 ├── database/ ← wraps apcore services/models (Postgres)
 └── vocab_builder/ ← builds custom AS2 types (Drink, Checkin, Venue...)
workers/
 └── untappd.go ← cron job, uses apcore services + vocab

Key apcore dependencies across the codebase:

Package Used for
github.com/go-fed/apcore apcore.Run() — the entire server lifecycle
github.com/go-fed/apcore/app app.Application, app.Framework, app.Router, app.Database interfaces
github.com/go-fed/apcore/framework/config config.Config (loaded from config.ini)
github.com/go-fed/apcore/framework/web web.Sessions
github.com/go-fed/apcore/framework/oauth2 oauth2.Server
github.com/go-fed/apcore/services services.Users, services.Followers, etc.
github.com/go-fed/apcore/models DB models (Users, Inboxes, Outboxes, ...)
github.com/go-fed/apcore/util util.ErrorLogger, util.InfoLogger, util.Context
github.com/go-fed/apcore/paths paths.UUID, paths.Followers
github.com/go-fed/activity/pub pub.SocialWrappedCallbacks, pub.Clock
github.com/go-fed/activity/streams Custom vocab serialization/deserialization
github.com/go-fed/activity/streams/vocab vocab.ActivityStreamsPerson, vocab.ActivityStreamsFollow, etc.

The custom streams package is a forked version at git.feneas.org/socialtap/activity that adds Socialtap-specific types (SocialtapDrink, SocialtapCheckin, SocialtapVenue, SocialtapManufacturer).


The Migration Challenge

The two libraries have fundamentally different design philosophies:

Aspect go-fed/apcore go-ap/activitypub
Role Full framework (server, DB, routing, OAuth) Vocabulary types only
Server lifecycle apcore.Run(app) handles everything You own the HTTP server
Routing app.Router abstraction Plain net/http / gorilla/mux
Database Built-in Postgres models & services You own the storage layer
Callbacks ApplyFederatingCallbacks, ApplySocialCallbacks You write the handlers
Config config.Config from config.ini You own config
Custom types Code-generated vocab extensions JSON-LD with custom properties

Proposed Migration Plan

Stage 1 — Decouple from apcore internals

Introduce your own interfaces to wrap apcore so the rest of the code doesn't import it directly. This makes Stage 2 much safer.

Steps:

  1. Create internal/config/config.go — own config struct, loaded from config.ini (keep same file format).
  2. Create internal/logger/logger.go — thin wrapper replacing util.ErrorLogger/util.InfoLogger.
  3. Create internal/storage/storage.go — define your own Storage interface (GetUser, GetFollowers, SaveActivity, etc.) backed by Postgres. Replace database/ calls to apcore services.
  4. Replace util.Context with plain context.Context everywhere.

Stage 2 — Replace vocab types

Swap github.com/go-fed/activity/streams/vocab for github.com/go-ap/activitypub.

Key mapping:

go-fed go-ap/activitypub
vocab.ActivityStreamsPerson activitypub.Person
vocab.ActivityStreamsFollow activitypub.Follow
vocab.ActivityStreamsOrderedCollectionPage activitypub.OrderedCollectionPage
vocab.ActivityStreamsImage activitypub.Image
.GetActivityStreamsActor() .Actor (direct field)
.GetActivityStreamsObject() .Object (direct field)
.GetIRI() / .IsIRI() activitypub.IRI type directly
Custom streams.NewSocialtapDrink() Plain activitypub.Object with Type + extra JSON-LD properties

Stage 3 — Replace the server framework

Replace apcore.Run() with your own HTTP server using net/http + gorilla/mux, implementing:

  • ActivityPub inbox/outbox endpoints
  • HTTP Signatures (use github.com/go-ap/httpsig)
  • WebFinger (github.com/go-ap/webfinger or similar)
  • OAuth2 (use golang.org/x/oauth2 or github.com/go-oauth2/oauth2)
  • Cron jobs (keep github.com/robfig/cron — no change needed)

github.com/go-ap/activitypub ← replaces go-fed/activity vocab
github.com/go-ap/jsonld ← JSON-LD serialization
github.com/go-ap/httpsig ← HTTP Signatures for S2S federation
github.com/gorilla/mux ← already present, keep
github.com/robfig/cron ← already present, keep
github.com/google/uuid ← already present, keep
## Codebase Analysis ### Current Architecture (go-fed/apcore) Here's the dependency map: ``` main.go └── activity/application.go ← implements app.Application, S2SApplication, C2SApplication ├── activity/federation_follow.go ← S2S Follow callback ├── handlers/ ← HTTP handlers (inbox, outbox, user, etc.) ├── database/ ← wraps apcore services/models (Postgres) └── vocab_builder/ ← builds custom AS2 types (Drink, Checkin, Venue...) workers/ └── untappd.go ← cron job, uses apcore services + vocab ``` **Key apcore dependencies across the codebase:** | Package | Used for | |---|---| | `github.com/go-fed/apcore` | `apcore.Run()` — the entire server lifecycle | | `github.com/go-fed/apcore/app` | `app.Application`, `app.Framework`, `app.Router`, `app.Database` interfaces | | `github.com/go-fed/apcore/framework/config` | `config.Config` (loaded from `config.ini`) | | `github.com/go-fed/apcore/framework/web` | `web.Sessions` | | `github.com/go-fed/apcore/framework/oauth2` | `oauth2.Server` | | `github.com/go-fed/apcore/services` | `services.Users`, `services.Followers`, etc. | | `github.com/go-fed/apcore/models` | DB models (Users, Inboxes, Outboxes, ...) | | `github.com/go-fed/apcore/util` | `util.ErrorLogger`, `util.InfoLogger`, `util.Context` | | `github.com/go-fed/apcore/paths` | `paths.UUID`, `paths.Followers` | | `github.com/go-fed/activity/pub` | `pub.SocialWrappedCallbacks`, `pub.Clock` | | `github.com/go-fed/activity/streams` | Custom vocab serialization/deserialization | | `github.com/go-fed/activity/streams/vocab` | `vocab.ActivityStreamsPerson`, `vocab.ActivityStreamsFollow`, etc. | The custom `streams` package is a **forked** version at `git.feneas.org/socialtap/activity` that adds Socialtap-specific types (`SocialtapDrink`, `SocialtapCheckin`, `SocialtapVenue`, `SocialtapManufacturer`). --- ## The Migration Challenge The two libraries have fundamentally different design philosophies: | Aspect | go-fed/apcore | go-ap/activitypub | |---|---|---| | **Role** | Full framework (server, DB, routing, OAuth) | Vocabulary types only | | **Server lifecycle** | `apcore.Run(app)` handles everything | You own the HTTP server | | **Routing** | `app.Router` abstraction | Plain `net/http` / gorilla/mux | | **Database** | Built-in Postgres models & services | You own the storage layer | | **Callbacks** | `ApplyFederatingCallbacks`, `ApplySocialCallbacks` | You write the handlers | | **Config** | `config.Config` from `config.ini` | You own config | | **Custom types** | Code-generated vocab extensions | JSON-LD with custom properties | --- ## Proposed Migration Plan ### Stage 1 — Decouple from apcore internals Introduce your own interfaces to wrap apcore so the rest of the code doesn't import it directly. This makes Stage 2 much safer. **Steps:** 1. Create `internal/config/config.go` — own config struct, loaded from `config.ini` (keep same file format). 2. Create `internal/logger/logger.go` — thin wrapper replacing `util.ErrorLogger`/`util.InfoLogger`. 3. Create `internal/storage/storage.go` — define your own `Storage` interface (GetUser, GetFollowers, SaveActivity, etc.) backed by Postgres. Replace `database/` calls to apcore services. 4. Replace `util.Context` with plain `context.Context` everywhere. ### Stage 2 — Replace vocab types Swap `github.com/go-fed/activity/streams/vocab` for `github.com/go-ap/activitypub`. **Key mapping:** | go-fed | go-ap/activitypub | |---|---| | `vocab.ActivityStreamsPerson` | `activitypub.Person` | | `vocab.ActivityStreamsFollow` | `activitypub.Follow` | | `vocab.ActivityStreamsOrderedCollectionPage` | `activitypub.OrderedCollectionPage` | | `vocab.ActivityStreamsImage` | `activitypub.Image` | | `.GetActivityStreamsActor()` | `.Actor` (direct field) | | `.GetActivityStreamsObject()` | `.Object` (direct field) | | `.GetIRI()` / `.IsIRI()` | `activitypub.IRI` type directly | | Custom `streams.NewSocialtapDrink()` | Plain `activitypub.Object` with `Type` + extra JSON-LD properties | ### Stage 3 — Replace the server framework Replace `apcore.Run()` with your own HTTP server using `net/http` + `gorilla/mux`, implementing: - ActivityPub inbox/outbox endpoints - HTTP Signatures (use `github.com/go-ap/httpsig`) - WebFinger (`github.com/go-ap/webfinger` or similar) - OAuth2 (use `golang.org/x/oauth2` or `github.com/go-oauth2/oauth2`) - Cron jobs (keep `github.com/robfig/cron` — no change needed) --- ## Recommended New `go.mod` Dependencies ``` github.com/go-ap/activitypub ← replaces go-fed/activity vocab github.com/go-ap/jsonld ← JSON-LD serialization github.com/go-ap/httpsig ← HTTP Signatures for S2S federation github.com/gorilla/mux ← already present, keep github.com/robfig/cron ← already present, keep github.com/google/uuid ← already present, keep ```
| Old | New | Why |
| --- | --- | --- |
| vocab.SocialtapDrink | vocab.Beer | Clearer domain name |
| vocab.SocialtapCheckin | vocab.Checkin | Drops generated prefix |
| vocab.SocialtapVenue | vocab.Venue | Same |
| vocab.SocialtapManufacturer | vocab.Manufacturer | Same |
| vocab.SocialtapRating | vocab.Rating | Same |
| params map[string]interface{} builder | Typed constructors | Type-safe, no runtime panics |
| streams.NewSocialtap* (code-gen) | Plain Go structs | No code generation needed |
| util.InfoLogger / util.ErrorLogger | Removed from vocab layer | Vocab shouldn't log |
| ConvertUntappdCheckin | FromUntappdCheckin | Idiomatic Go naming |
| Deleted | Replaced by |
| --- | --- |
| activity/ (entire package) | internal/ap/ + internal/server/ |
| database/ (entire package) | internal/storage/ |
| handlers/ (entire package) | internal/ap/ handlers + internal/webfinger/ |
| vocab_builder/ | internal/vocab/ (Stage 2) |
| github.com/go-fed/apcore | removed entirely |
| github.com/go-fed/activity | github.com/go-ap/activitypub |
| util.ErrorLogger / util.InfoLogger | internal/logger (log/slog) |
| util.Context | context.Context |
| paths.UUID, paths.UUIDIRIFor | internal/ap/actor.go helpers |
| services.* | internal/storage.Storage interface |
| models.* | Postgres schema in internal/storage/postgres.go |
| Path | Replaces |
| --- | --- |
| internal/ap/actor_handler.go | handlers/app_user.go |
| internal/ap/collections.go | handlers/app_followers.go + app_following.go |
| internal/handlers/checkins.go | handlers/checkins.go |
| internal/handlers/user_info.go | handlers/user_info.go |
| internal/handlers/search.go | handlers/search_result.go |
| internal/handlers/conversation.go | handlers/conversation.go |
| internal/handlers/settings.go | handlers/settings.go + handlers/token.go |
| internal/auth/jwt.go | apcore f.Validate() + sessions |
| workers/untappd.go | workers/untappd.go (full rewrite) |
| internal/server/server.go | activity/application.go + apcore.Run() |
everything related to deleting stuff
What is working so far
1. Register a new user
2. Login as user
3. Post a new checkin
4. The new checkin is displayed in the profile section
This pull request is marked as a work in progress.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin goap_migration_decouple:goap_migration_decouple
git switch goap_migration_decouple

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch master
git merge --no-ff goap_migration_decouple
git switch goap_migration_decouple
git rebase master
git switch master
git merge --ff-only goap_migration_decouple
git switch goap_migration_decouple
git rebase master
git switch master
git merge --no-ff goap_migration_decouple
git switch master
git merge --squash goap_migration_decouple
git switch master
git merge --ff-only goap_migration_decouple
git switch master
git merge goap_migration_decouple
git push origin master
Sign in to join this conversation.
No reviewers
Labels
Clear labels
No items
No labels
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
socialtap/server!1
Reference in a new issue
socialtap/server
No description provided.
Delete branch "goap_migration_decouple"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?