Skip to content

Guaderxx/gap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gap — Go ActivityPub

Go Reference Go Version License

A lightweight, zero-dependency Go library implementing the ActivityPub protocol (ActivityStreams 2.0). Designed for building federated social applications — Mastodon-compatible servers, bots, clients, and tools.

GAP stands for Go ActivityPub.
The name also happens to reflect a small personal coincidence at the time of creation.

Features

  • ActivityStreams 2.0 types — Actor, Note, Activity, Collection, WebFinger, NodeInfo
  • HTTP Signatures — draft-cavage-http-signatures (RSA-SHA256 sign & verify)
  • LD Signatures — RsaSignature2017 for backward compatibility
  • Safe HTTP client — SSRF protection (blocks private/internal IPs)
  • Activity delivery — signed POST to remote inboxes
  • Key generation — RSA-2048 key pair generation

Installation

go get github.com/Guaderxx/gap

Quick Start

Create an ActivityPub Actor

actor := gap.Actor{
    Context: []string{
        gap.ContextActivityStreams,
        gap.ContextSecurity,
    },
    ID:                "https://example.com/users/alice",
    Type:              gap.ActorPerson,  // use constants for type safety
    PreferredUsername: "alice",
    Name:              "Alice",
    Inbox:             "https://example.com/users/alice/inbox",
    Outbox:            "https://example.com/users/alice/outbox",
    Followers:         "https://example.com/users/alice/followers",
    Following:         "https://example.com/users/alice/following",
    PublicKey: &gap.PublicKey{
        ID:           "https://example.com/users/alice#main-key",
        Owner:        "https://example.com/users/alice",
        PublicKeyPem: publicKeyPEM,
    },
}

Sign and Deliver an Activity

// Create a Follow activity
follow := gap.Activity{
    Context: []string{gap.ContextActivityStreams},
    Type:    gap.ActivityFollow,  // use constants for type safety
    Actor:   "https://example.com/users/alice",
    Object:  "https://mastodon.example/users/bob",
}

body, _ := json.Marshal(follow)

// Deliver it to Bob's inbox
err := gap.DeliverActivity(
    "https://mastodon.example/users/bob/inbox",
    body,
    "https://example.com/users/alice#main-key",
    privateKeyPEM,
)

Safe HTTP Client

client := gap.NewSafeClient()

// This will be blocked (private IP)
resp, err := client.Get("http://10.0.0.1/api")
// err: gap: connection blocked by SSRF protection

// This works normally
resp, err := client.Get("https://mastodon.social/.well-known/nodeinfo")

WebFinger Discovery

resp := gap.WebFingerResponse{
    Subject: "acct:alice@example.com",
    Links: []gap.WebFingerLink{
        {
            Rel:  "self",
            Type: "application/activity+json",
            Href: "https://example.com/users/alice",
        },
    },
}

Package Overview

Package Contents
gap All types and functions in a single flat package

Types

Type Description
Actor ActivityPub actor (Person, Application, Service)
Activity ActivityPub activity (Create, Follow, Like, etc.)
Note ActivityPub note (equivalent to a Mastodon status)
Collection Ordered collection (followers, following, outbox)
PublicKey Actor's public key for HTTP Signatures
WebFingerResponse RFC 7033 WebFinger JRD response
NodeInfo NodeInfo 2.0 instance metadata
Image Attached image in ActivityPub documents
LDKeyPair RSA key pair for Linked Data Signatures

Constants

Context URIs:

Constant Value
ContextActivityStreams https://www.w3.org/ns/activitystreams
ContextSecurity https://w3id.org/security/v1
PublicAddress https://www.w3.org/ns/activitystreams#Public

Activity Types (gap.ActivityXxx):

Constant Value Mastodon equivalent
ActivityAccept Accept Accept follow
ActivityAdd Add Add to collection
ActivityAnnounce Announce Boost / reblog
ActivityBlock Block Block user
ActivityCreate Create Post a status
ActivityDelete Delete Delete a status
ActivityFlag Flag Report
ActivityFollow Follow Follow user
ActivityLike Like Favourite
ActivityMove Move Account migration
ActivityReject Reject Reject follow
ActivityRemove Remove Remove from collection
ActivityUndo Undo Undo an action
ActivityUpdate Update Edit a status/profile
ActivityView View View

Actor Types (gap.ActorXxx):

Constant Value
ActorPerson Person
ActorApplication Application
ActorService Service
ActorGroup Group
ActorOrganization Organization

Object Types (gap.ObjectXxx):

Constant Value
ObjectNote Note
ObjectArticle Article
ObjectDocument Document
ObjectImage Image
ObjectVideo Video
ObjectAudio Audio
ObjectPage Page
ObjectEvent Event
ObjectPlace Place
ObjectQuestion Question
ObjectCollectionType OrderedCollection

HTTP Signatures

Function Description
SignRequest(req, keyID, privateKeyPEM) Sign an HTTP request with RSA-SHA256
VerifyRequest(req, publicKeyPEM) Verify an incoming HTTP signature (returns bool)
AddDateHeader(req) Set the Date header for signing
AddDigestHeader(req, body) Set the Digest header with SHA-256
DeliverActivity(inbox, body, keyID, privateKeyPEM) Sign & POST an activity to a remote inbox
GenerateKeyPair() Generate a RSA-2048 key pair (returns PEM strings)

LD Signatures

Function Description
SignJSONLD(doc, keyPair) Sign a JSON-LD document with RsaSignature2017
VerifyJSONLD(doc, sig, publicKeyPEM) Verify a Linked Data Signature

Safe Client

Function/Type Description
NewSafeClient() Create an HTTP client with SSRF protection
SafeClient.Get(url) Safe GET request
SafeClient.Post(url, contentType, body) Safe POST request
ResolveActorURI(uri) Extract username & domain from an actor URI

Architecture

your-app/
├── handlers/      # Gin/Echo/Chi HTTP handlers
├── federation/    # ActivityPub server logic
├── storage/       # Database layer (your choice)
└── ...
    └── imports github.com/Guaderxx/gap  # Protocol types & crypto

Gap is framework-agnostic. It provides:

  • Types — use them in your JSON serialization
  • Crypto — sign and verify requests
  • Client — make safe HTTP calls to remote servers

It does NOT provide:

  • Database storage
  • HTTP routing
  • Queue/worker systems
  • Real-time streaming

These belong in your application layer — gap is the protocol foundation.

Example Application

See example/main.go for a complete working example of a minimal ActivityPub server.

Dependencies

Zero external dependencies. Gap uses only the Go standard library:

  • crypto/* — RSA, SHA-256, ECDH, AES-GCM
  • net/http — HTTP client with custom transport
  • encoding/json, encoding/pem, encoding/base64

License

MIT. See LICENSE.

About

ActivityPub protocol (ActivityStreams 2.0)

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages