8.0 KiB
8.0 KiB
ActivityPub Testing Quick Reference
Quick Test Commands
1. Test WebFinger
curl "http://solar.local:5000/.well-known/webfinger?resource=acct:username@solar.local"
2. Fetch Actor Profile
curl -H "Accept: application/activity+json" \
http://solar.local:5000/activitypub/actors/username
3. Get Outbox
curl -H "Accept: application/activity+json" \
http://solar.local:5000/activitypub/actors/username/outbox
4. Send Test Follow (from remote)
curl -X POST http://solar.local:5000/activitypub/actors/username/inbox \
-H "Content-Type: application/activity+json" \
-d '{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://mastodon.local:3001/follow-123",
"type": "Follow",
"actor": "https://mastodon.local:3001/users/remoteuser",
"object": "https://solar.local:5000/activitypub/actors/username"
}'
5. Send Test Create (post)
curl -X POST http://solar.local:5000/activitypub/actors/username/inbox \
-H "Content-Type: application/activity+json" \
-d '{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://mastodon.local:3001/post-123",
"type": "Create",
"actor": "https://mastodon.local:3001/users/remoteuser",
"object": {
"id": "https://mastodon.local:3001/objects/post-123",
"type": "Note",
"content": "Hello from Mastodon! @username@solar.local",
"attributedTo": "https://mastodon.local:3001/users/remoteuser",
"to": ["https://www.w3.org/ns/activitystreams#Public"]
}
}'
6. Send Test Like
curl -X POST http://solar.local:5000/activitypub/actors/username/inbox \
-H "Content-Type: application/activity+json" \
-d '{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://mastodon.local:3001/like-123",
"type": "Like",
"actor": "https://mastodon.local:3001/users/remoteuser",
"object": "https://solar.local:5000/activitypub/objects/post-id"
}'
Database Queries
Check Actors
SELECT id, uri, username, display_name, instance_id
FROM fediverse_actors;
Check Contents
SELECT id, uri, type, content, actor_id, created_at
FROM fediverse_contents
ORDER BY created_at DESC
LIMIT 20;
Check Relationships
SELECT r.id, a1.uri as actor, a2.uri as target, r.state, r.is_following
FROM fediverse_relationships r
JOIN fediverse_actors a1 ON r.actor_id = a1.id
JOIN fediverse_actors a2 ON r.target_actor_id = a2.id;
Check Activities
SELECT type, status, error_message, created_at
FROM fediverse_activities
ORDER BY created_at DESC
LIMIT 20;
Check Reactions
SELECT r.type, c.uri as content_uri, a.uri as actor_uri
FROM fediverse_reactions r
JOIN fediverse_contents c ON r.content_id = c.id
JOIN fediverse_actors a ON r.actor_id = a.id;
Check Keys in Publisher
SELECT id, name, meta
FROM publishers
WHERE meta IS NOT NULL;
Docker Commands
Start Mastodon
docker-compose -f docker-compose.mastodon-test.yml up -d
View Mastodon Logs
docker-compose -f docker-compose.mastodon-test.yml logs -f web
Stop Mastodon
docker-compose -f docker-compose.mastodon-test.yml down
Start GoToSocial
docker-compose -f docker-compose.gotosocial.yml up -d
Solar Network Commands
Run Migrations
cd DysonNetwork.Sphere
dotnet ef database update
Run with Debug Logging
dotnet run --project DysonNetwork.Sphere -- --logging:LogLevel:DysonNetwork.Sphere.ActivityPub=Trace
Common Response Codes
| Code | Meaning |
|---|---|
| 200 | Success |
| 202 | Accepted (activity queued) |
| 401 | Unauthorized (invalid signature) |
| 404 | Not found (user/post doesn't exist) |
| 400 | Bad request (invalid activity) |
Activity Status Codes
| Status | Code | Meaning |
|---|---|---|
| Pending | 0 | Activity waiting to be processed |
| Processing | 1 | Activity being processed |
| Completed | 2 | Activity successfully processed |
| Failed | 3 | Activity processing failed |
Relationship States
| State | Code | Meaning |
|---|---|---|
| Pending | 0 | Follow request sent, waiting for Accept |
| Accepted | 1 | Follow accepted, relationship active |
| Rejected | 2 | Follow rejected |
Troubleshooting
"Failed to verify signature"
Check: Signature header format
# Should be:
Signature: keyId="...",algorithm="rsa-sha256",headers="...",signature="..."
Check: Public key in actor profile
curl -H "Accept: application/activity+json" \
http://solar.local:5000/activitypub/actors/username | jq '.publicKey'
"Actor not found"
Check: Actor exists in database
psql -d dyson_network -c \
"SELECT * FROM fediverse_actors WHERE uri = '...';"
Check: Actor URL is accessible
curl -v http://remote-instance.com/users/username
"Content already exists"
This is normal behavior - the system is deduplicating.
"Target publisher not found"
Check: Publisher exists
psql -d dyson_network -c \
"SELECT * FROM publishers WHERE name = '...';"
Quick Test Sequence
Full Federation Test
# 1. Start both instances
docker-compose -f docker-compose.mastodon-test.yml up -d
dotnet run --project DysonNetwork.Sphere
# 2. Test WebFinger
curl "http://solar.local:5000/.well-known/webfinger?resource=acct:solaruser@solar.local"
# 3. Get Actor
curl -H "Accept: application/activity+json" \
http://solar.local:5000/activitypub/actors/solaruser
# 4. Send Follow from Mastodon
# (Do this in Mastodon UI or use curl above)
# 5. Check database
psql -d dyson_network -c "SELECT * FROM fediverse_relationships;"
# 6. Send Create (post) from Mastodon
# (Use curl command above)
# 7. Check content
psql -d dyson_network -c "SELECT * FROM fediverse_contents;"
# 8. Send Like from Mastodon
# (Use curl command above)
# 9. Check reactions
psql -d dyson_network -c "SELECT * FROM fediverse_reactions;"
# 10. Check activities
psql -d dyson_network -c "SELECT type, status FROM fediverse_activities;"
Test URLs
| Instance | Web | API | ActivityPub |
|---|---|---|---|
| Solar Network | http://solar.local:5000 | http://solar.local:5000/api | http://solar.local:5000/activitypub |
| Mastodon | http://mastodon.local:3001 | http://mastodon.local:3001/api/v1 | http://mastodon.local:3001/inbox |
Environment Variables
Solar Network
export SOLAR_DOMAIN="solar.local"
export SOLAR_URL="http://solar.local:5000"
Mastodon
export MASTODON_DOMAIN="mastodon.local"
export MASTODON_URL="http://mastodon.local:3001"
Useful jq Commands
Extract Actor ID
curl ... | jq '.id'
Extract Inbox URL
curl ... | jq '.inbox'
Extract Public Key
curl ... | jq '.publicKey.publicKeyPem'
Pretty Print Activity
curl ... | jq '.'
Extract Activity Type
curl ... | jq '.type'
Network Setup
/etc/hosts
127.0.0.1 solar.local
127.0.0.1 mastodon.local
127.0.0.1 gotosocial.local
Ports Used
- Solar Network: 5000
- Mastodon: 3001 (web), 4000 (streaming)
- GoToSocial: 3002
- PostgreSQL: 5432
- Redis: 6379
- Elasticsearch: 9200
File Locations
Docker Compose Files
docker-compose.mastodon-test.ymldocker-compose.gotosocial.yml
Environment Files
.env.mastodon
Data Volumes
./mastodon-data/./gotosocial-data/
Clean Up Commands
# Reset database
psql -d dyson_network <<EOF
TRUNCATE fediverse_activities CASCADE;
TRUNCATE fediverse_relationships CASCADE;
TRUNCATE fediverse_reactions CASCADE;
TRUNCATE fediverse_contents CASCADE;
TRUNCATE fediverse_actors CASCADE;
TRUNCATE fediverse_instances CASCADE;
UPDATE publishers SET meta = NULL WHERE meta IS NOT NULL;
EOF
# Reset everything
docker-compose -f docker-compose.mastodon-test.yml down -v
docker-compose -f docker-compose.gotosocial.yml down -v
psql -d dyson_network <<EOF
DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
EOF
dotnet ef database drop
dotnet ef database update