🔨 Add some tests utilities of activity pub
This commit is contained in:
820
docs/ACTIVITYPUB_TESTING_GUIDE.md
Normal file
820
docs/ACTIVITYPUB_TESTING_GUIDE.md
Normal file
@@ -0,0 +1,820 @@
|
||||
# ActivityPub Testing Guide for Solar Network
|
||||
|
||||
This guide will help you test the ActivityPub implementation in Solar Network, starting with a self-hosted instance and then moving to a real instance.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- ✅ Solar Network codebase with ActivityPub implementation
|
||||
- ✅ Docker installed (for running Mastodon/Fediverse instances)
|
||||
- ✅ PostgreSQL database running
|
||||
- ✅ `.NET 10` SDK
|
||||
|
||||
## Part 1: Set Up a Self-Hosted Test Instance
|
||||
|
||||
### Option A: Using Mastodon (Recommended for Compatibility)
|
||||
|
||||
#### 1. Create a Docker Compose File
|
||||
|
||||
Create `docker-compose.mastodon-test.yml`:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
db:
|
||||
restart: always
|
||||
image: postgres:14-alpine
|
||||
environment:
|
||||
POSTGRES_USER: mastodon
|
||||
POSTGRES_PASSWORD: mastodon_password
|
||||
POSTGRES_DB: mastodon
|
||||
networks:
|
||||
- mastodon_network
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready", "-U", "mastodon"]
|
||||
interval: 5s
|
||||
retries: 5
|
||||
|
||||
redis:
|
||||
restart: always
|
||||
image: redis:7-alpine
|
||||
networks:
|
||||
- mastodon_network
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 5s
|
||||
retries: 5
|
||||
|
||||
es:
|
||||
restart: always
|
||||
image: docker.elastic.co/elasticsearch:8.10.2
|
||||
environment:
|
||||
- "discovery.type=single-node"
|
||||
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
||||
- "xpack.security.enabled=false"
|
||||
networks:
|
||||
- mastodon_network
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -silent http://localhost:9200/_cluster/health || exit 1"]
|
||||
interval: 10s
|
||||
retries: 10
|
||||
|
||||
web:
|
||||
restart: always
|
||||
image: tootsuite/mastodon:latest
|
||||
env_file: .env.mastodon
|
||||
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
|
||||
ports:
|
||||
- "3001:3000"
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
- es
|
||||
networks:
|
||||
- mastodon_network
|
||||
volumes:
|
||||
- ./mastodon-data/public:/mastodon/public/system
|
||||
|
||||
streaming:
|
||||
restart: always
|
||||
image: tootsuite/mastodon:latest
|
||||
env_file: .env.mastodon
|
||||
command: node ./streaming
|
||||
ports:
|
||||
- "4000:4000"
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
networks:
|
||||
- mastodon_network
|
||||
|
||||
sidekiq:
|
||||
restart: always
|
||||
image: tootsuite/mastodon:latest
|
||||
env_file: .env.mastodon
|
||||
command: bundle exec sidekiq
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
networks:
|
||||
- mastodon_network
|
||||
|
||||
networks:
|
||||
mastodon_network:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
#### 2. Create Environment File
|
||||
|
||||
Create `.env.mastodon`:
|
||||
|
||||
```bash
|
||||
# Federation
|
||||
LOCAL_DOMAIN=mastodon.local
|
||||
LOCAL_HTTPS=false
|
||||
|
||||
# Database
|
||||
DB_HOST=db
|
||||
DB_PORT=5432
|
||||
DB_USER=mastodon
|
||||
DB_NAME=mastodon
|
||||
DB_PASS=mastodon_password
|
||||
|
||||
# Redis
|
||||
REDIS_HOST=redis
|
||||
REDIS_PORT=6379
|
||||
|
||||
# Elasticsearch
|
||||
ES_ENABLED=true
|
||||
ES_HOST=es
|
||||
ES_PORT=9200
|
||||
|
||||
# Secrets (generate these!)
|
||||
SECRET_KEY_BASE=change_me_to_a_random_string_at_least_32_chars
|
||||
OTP_SECRET=change_me_to_another_random_string
|
||||
|
||||
# Defaults
|
||||
SINGLE_USER_MODE=false
|
||||
DEFAULT_LOCALE=en
|
||||
```
|
||||
|
||||
**Generate secrets:**
|
||||
```bash
|
||||
# Run these to generate random secrets
|
||||
openssl rand -base64 32
|
||||
```
|
||||
|
||||
#### 3. Start Mastodon
|
||||
|
||||
```bash
|
||||
docker-compose -f docker-compose.mastodon-test.yml up -d
|
||||
|
||||
# Check logs
|
||||
docker-compose -f docker-compose.mastodon-test.yml logs -f web
|
||||
```
|
||||
|
||||
Wait for the web service to be healthy (may take 2-5 minutes).
|
||||
|
||||
#### 4. Create a Mastodon Account
|
||||
|
||||
```bash
|
||||
# Run this command to create an admin account
|
||||
docker-compose -f docker-compose.mastodon-test.yml exec web \
|
||||
bin/tootctl accounts create \
|
||||
testuser \
|
||||
testuser@mastodon.local \
|
||||
--email=test@example.com \
|
||||
--confirmed \
|
||||
--role=admin \
|
||||
--approve
|
||||
```
|
||||
|
||||
Set password: `TestPassword123!`
|
||||
|
||||
#### 5. Update Your /etc/hosts
|
||||
|
||||
```bash
|
||||
sudo nano /etc/hosts
|
||||
```
|
||||
|
||||
Add:
|
||||
```
|
||||
127.0.0.1 mastodon.local
|
||||
127.0.0.1 solar.local
|
||||
```
|
||||
|
||||
### Option B: Using GoToSocial (Lightweight Alternative)
|
||||
|
||||
Create `docker-compose.gotosocial.yml`:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
gotosocial:
|
||||
image: superseriousbusiness/gotosocial:latest
|
||||
environment:
|
||||
- GTS_HOST=gotosocial.local
|
||||
- GTS_ACCOUNT_DOMAIN=gotosocial.local
|
||||
- GTS_PROTOCOL=http
|
||||
- GTS_DB_TYPE=sqlite
|
||||
- GTS_DB_ADDRESS=/gotosocial/data/sqlite.db
|
||||
- GTS_STORAGE_LOCAL_BASE_PATH=/gotosocial/data/storage
|
||||
ports:
|
||||
- "3002:8080"
|
||||
volumes:
|
||||
- ./gotosocial-data:/gotosocial/data
|
||||
|
||||
networks:
|
||||
default:
|
||||
```
|
||||
|
||||
Start it:
|
||||
```bash
|
||||
docker-compose -f docker-compose.gotosocial.yml up -d
|
||||
```
|
||||
|
||||
Create account:
|
||||
```bash
|
||||
docker-compose -f docker-compose.gotosocial.yml exec gotosocial \
|
||||
/gotosocial/gotosocial admin account create \
|
||||
--username testuser \
|
||||
--email test@example.com \
|
||||
--password TestPassword123!
|
||||
```
|
||||
|
||||
## Part 2: Configure Solar Network for Federation
|
||||
|
||||
### 1. Update appsettings.json
|
||||
|
||||
Edit `DysonNetwork.Sphere/appsettings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"ActivityPub": {
|
||||
"Domain": "solar.local",
|
||||
"EnableFederation": true
|
||||
},
|
||||
"Kestrel": {
|
||||
"Endpoints": {
|
||||
"Http": {
|
||||
"Url": "http://solar.local:5000"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Update /etc/hosts
|
||||
|
||||
Add both instances:
|
||||
```
|
||||
127.0.0.1 mastodon.local
|
||||
127.0.0.1 solar.local
|
||||
127.0.0.1 gotosocial.local
|
||||
```
|
||||
|
||||
### 3. Apply Database Migrations
|
||||
|
||||
```bash
|
||||
cd DysonNetwork.Sphere
|
||||
dotnet ef database update
|
||||
```
|
||||
|
||||
### 4. Start Solar Network
|
||||
|
||||
```bash
|
||||
dotnet run --project DysonNetwork.Sphere
|
||||
```
|
||||
|
||||
Solar Network should now be running on `http://solar.local:5000`
|
||||
|
||||
## Part 3: Create Test Users
|
||||
|
||||
### In Solar Network
|
||||
|
||||
1. Open http://solar.local:5000 (or your web interface)
|
||||
2. Create a new account/publisher named `solaruser`
|
||||
3. Note down the publisher ID for later
|
||||
|
||||
**Or via API** (if you have an existing account):
|
||||
|
||||
```bash
|
||||
# First, create a publisher in Solar Network
|
||||
curl -X POST http://solar.local:5000/api/publishers \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-d '{
|
||||
"name": "solaruser",
|
||||
"nick": "Solar User",
|
||||
"bio": "Testing ActivityPub federation!",
|
||||
"type": 0
|
||||
}'
|
||||
```
|
||||
|
||||
### In Mastodon
|
||||
|
||||
Open http://mastodon.local:3001 and log in with:
|
||||
- Username: `testuser`
|
||||
- Password: `TestPassword123!`
|
||||
|
||||
## Part 4: Test Federation Scenarios
|
||||
|
||||
### Test 1: WebFinger Discovery
|
||||
|
||||
**Goal**: Verify Solar Network is discoverable
|
||||
|
||||
```bash
|
||||
# Query Solar Network's WebFinger endpoint
|
||||
curl -v "http://solar.local:5000/.well-known/webfinger?resource=acct:solaruser@solar.local"
|
||||
|
||||
# Expected response (200 OK):
|
||||
{
|
||||
"subject": "acct:solaruser@solar.local",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"type": "application/activity+json",
|
||||
"href": "https://solar.local:5000/activitypub/actors/solaruser"
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.net/rel/profile-page",
|
||||
"type": "text/html",
|
||||
"href": "https://solar.local:5000/users/solaruser"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Test 2: Fetch Actor Profile
|
||||
|
||||
**Goal**: Get ActivityPub actor JSON
|
||||
|
||||
```bash
|
||||
# Fetch Solar Network actor from Mastodon
|
||||
curl -H "Accept: application/activity+json" \
|
||||
http://solar.local:5000/activitypub/actors/solaruser
|
||||
|
||||
# Expected response includes:
|
||||
{
|
||||
"@context": ["https://www.w3.org/ns/activitystreams"],
|
||||
"id": "https://solar.local:5000/activitypub/actors/solaruser",
|
||||
"type": "Person",
|
||||
"preferredUsername": "solaruser",
|
||||
"inbox": "https://solar.local:5000/activitypub/actors/solaruser/inbox",
|
||||
"outbox": "https://solar.local:5000/activitypub/actors/solaruser/outbox",
|
||||
"followers": "https://solar.local:5000/activitypub/actors/solaruser/followers",
|
||||
"publicKey": {
|
||||
"id": "https://solar.local:5000/activitypub/actors/solaruser#main-key",
|
||||
"owner": "https://solar.local:5000/activitypub/actors/solaruser",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\n..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Test 3: Follow from Mastodon to Solar Network
|
||||
|
||||
**Goal**: Mastodon user follows Solar Network user
|
||||
|
||||
1. **In Mastodon**:
|
||||
- Go to http://mastodon.local:3001
|
||||
- In search bar, type: `@solaruser@solar.local`
|
||||
- Click the follow button
|
||||
|
||||
2. **Verify in Solar Network**:
|
||||
```bash
|
||||
# Check database for relationship
|
||||
psql -d dyson_network -c \
|
||||
"SELECT * FROM fediverse_relationships WHERE is_local_actor = true;"
|
||||
```
|
||||
|
||||
3. **Check Solar Network logs**:
|
||||
Should see:
|
||||
```
|
||||
Processing activity type: Follow from actor: ...
|
||||
Processed follow from ... to ...
|
||||
```
|
||||
|
||||
4. **Verify Mastodon receives Accept**:
|
||||
- Check Mastodon logs for Accept activity
|
||||
- Verify follow appears as accepted in Mastodon
|
||||
|
||||
### Test 4: Follow from Solar Network to Mastodon
|
||||
|
||||
**Goal**: Solar Network user follows Mastodon user
|
||||
|
||||
You'll need to call the ActivityPub delivery service:
|
||||
|
||||
```bash
|
||||
# Via API (you'll need to implement this endpoint):
|
||||
curl -X POST http://solar.local:5000/api/activitypub/follow \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-d '{
|
||||
"targetActorUri": "http://mastodon.local:3001/users/testuser"
|
||||
}'
|
||||
```
|
||||
|
||||
**Or test directly with curl** (simulating a Follow activity):
|
||||
|
||||
```bash
|
||||
# Create a Follow activity
|
||||
curl -X POST http://solar.local:5000/activitypub/actors/solaruser/inbox \
|
||||
-H "Content-Type: application/activity+json" \
|
||||
-d '{
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"id": "http://mastodon.local:3001/test-follow-activity",
|
||||
"type": "Follow",
|
||||
"actor": "http://mastodon.local:3001/users/testuser",
|
||||
"object": "https://solar.local:5000/activitypub/actors/solaruser"
|
||||
}'
|
||||
```
|
||||
|
||||
### Test 5: Create a Post in Solar Network
|
||||
|
||||
**Goal**: Post federates to Mastodon
|
||||
|
||||
1. **Create a post via Solar Network API**:
|
||||
```bash
|
||||
curl -X POST http://solar.local:5000/api/posts \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-d '{
|
||||
"content": "Hello fediverse! Testing ActivityPub from Solar Network! 🚀",
|
||||
"visibility": 0,
|
||||
"publisherId": "PUBLISHER_ID"
|
||||
}'
|
||||
```
|
||||
|
||||
2. **Wait a few seconds**
|
||||
|
||||
3. **Check in Mastodon**:
|
||||
- Go to http://mastodon.local:3001
|
||||
- The post should appear in the federated timeline
|
||||
- It should show `@solaruser@solar.local` as the author
|
||||
|
||||
4. **Verify Solar Network logs**:
|
||||
```
|
||||
Successfully sent activity to http://mastodon.local:3001/inbox
|
||||
```
|
||||
|
||||
### Test 6: Like from Mastodon
|
||||
|
||||
**Goal**: Mastodon user likes a Solar Network post
|
||||
|
||||
1. **In Mastodon**:
|
||||
- Find the Solar Network post
|
||||
- Click the favorite/like button
|
||||
|
||||
2. **Verify in Solar Network**:
|
||||
```bash
|
||||
psql -d dyson_network -c \
|
||||
"SELECT * FROM fediverse_reactions;"
|
||||
```
|
||||
|
||||
3. **Check Solar Network logs**:
|
||||
```
|
||||
Processing activity type: Like from actor: ...
|
||||
Processed like from ...
|
||||
```
|
||||
|
||||
### Test 7: Reply from Mastodon
|
||||
|
||||
**Goal**: Reply federates to Solar Network
|
||||
|
||||
1. **In Mastodon**:
|
||||
- Reply to the Solar Network post
|
||||
- Write: "@solaruser Nice to meet you!"
|
||||
|
||||
2. **Verify in Solar Network**:
|
||||
```bash
|
||||
psql -d dyson_network -c \
|
||||
"SELECT * FROM fediverse_contents WHERE in_reply_to IS NOT NULL;"
|
||||
```
|
||||
|
||||
## Part 5: Debugging and Troubleshooting
|
||||
|
||||
### Enable Detailed Logging
|
||||
|
||||
Edit `appsettings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"DysonNetwork.Sphere.ActivityPub": "Trace"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Check Database State
|
||||
|
||||
```bash
|
||||
# Check actors
|
||||
psql -d dyson_network -c \
|
||||
"SELECT uri, username, display_name FROM fediverse_actors;"
|
||||
|
||||
# Check contents
|
||||
psql -d dyson_network -c \
|
||||
"SELECT uri, type, content FROM fediverse_contents;"
|
||||
|
||||
# Check relationships
|
||||
psql -d dyson_network -c \
|
||||
"SELECT * FROM fediverse_relationships;"
|
||||
|
||||
# Check activities
|
||||
psql -d dyson_network -c \
|
||||
"SELECT type, status, error_message FROM fediverse_activities;"
|
||||
|
||||
# Check failed activities
|
||||
psql -d dyson_network -c \
|
||||
"SELECT * FROM fediverse_activities WHERE status = 3;" # 3 = Failed
|
||||
```
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### Issue: "Failed to verify signature"
|
||||
|
||||
**Cause**: HTTP Signature verification failed
|
||||
|
||||
**Solutions**:
|
||||
1. Check the signature header format
|
||||
2. Verify public key matches actor's keyId
|
||||
3. Ensure Date header is within 5 minutes
|
||||
4. Check host header matches request URL
|
||||
|
||||
#### Issue: "Target actor or inbox not found"
|
||||
|
||||
**Cause**: Remote actor not fetched yet
|
||||
|
||||
**Solutions**:
|
||||
1. Manually fetch the actor first
|
||||
2. Check actor URL is correct
|
||||
3. Verify remote instance is accessible
|
||||
|
||||
#### Issue: "Content already exists"
|
||||
|
||||
**Cause**: Duplicate activity received
|
||||
|
||||
**Solutions**:
|
||||
1. This is normal - deduplication is working
|
||||
2. Check if content appears correctly
|
||||
|
||||
#### Issue: CORS errors when testing from browser
|
||||
|
||||
**Cause**: Browser blocking cross-origin requests
|
||||
|
||||
**Solutions**:
|
||||
1. Use curl for API testing
|
||||
2. Or disable CORS in development
|
||||
3. Test directly from Mastodon interface
|
||||
|
||||
### View HTTP Signatures
|
||||
|
||||
For debugging, you can inspect the signature:
|
||||
|
||||
```bash
|
||||
# From Mastodon to Solar Network
|
||||
curl -v -X POST http://solar.local:5000/activitypub/actors/solaruser/inbox \
|
||||
-H "Content-Type: application/activity+json" \
|
||||
-d '{"type":"Follow",...}'
|
||||
```
|
||||
|
||||
Look for the `Signature` header in the output.
|
||||
|
||||
### Test HTTP Signature Verification Manually
|
||||
|
||||
Create a test script `test-signature.js`:
|
||||
|
||||
```javascript
|
||||
const crypto = require('crypto');
|
||||
|
||||
// Test signature verification
|
||||
const publicKey = `-----BEGIN PUBLIC KEY-----
|
||||
...
|
||||
-----END PUBLIC KEY-----`;
|
||||
|
||||
const signingString = `(request-target): post /activitypub/actors/solaruser/inbox
|
||||
host: solar.local:5000
|
||||
date: ${new Date().toUTCString()}
|
||||
content-length: ...`;
|
||||
|
||||
const signature = '...';
|
||||
|
||||
const verify = crypto.createVerify('SHA256');
|
||||
verify.update(signingString);
|
||||
const isValid = verify.verify(publicKey, signature, 'base64');
|
||||
|
||||
console.log('Signature valid:', isValid);
|
||||
```
|
||||
|
||||
## Part 6: Test with a Real Instance
|
||||
|
||||
### Preparing for Public Federation
|
||||
|
||||
1. **Get a real domain** (e.g., via ngrok or a VPS)
|
||||
|
||||
```bash
|
||||
# Using ngrok for testing
|
||||
ngrok http 5000
|
||||
|
||||
# This gives you: https://random-id.ngrok-free.app
|
||||
```
|
||||
|
||||
2. **Update Solar Network config**:
|
||||
|
||||
```json
|
||||
{
|
||||
"ActivityPub": {
|
||||
"Domain": "your-domain.com",
|
||||
"EnableFederation": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **Update DNS** (if using real domain):
|
||||
- Add A record pointing to your server
|
||||
- Configure HTTPS (required for production federation)
|
||||
|
||||
4. **Test WebFinger with your domain**:
|
||||
|
||||
```bash
|
||||
curl "https://your-domain.com/.well-known/webfinger?resource=acct:username@your-domain.com"
|
||||
```
|
||||
|
||||
### Test with Mastodon.social
|
||||
|
||||
1. **Create a Mastodon.social account**
|
||||
- Go to https://mastodon.social
|
||||
- Sign up for a test account
|
||||
|
||||
2. **Search for your Solar Network user**:
|
||||
- In Mastodon.social search: `@username@your-domain.com`
|
||||
- Click follow
|
||||
|
||||
3. **Create a post in Solar Network**
|
||||
- Should appear in Mastodon.social
|
||||
|
||||
4. **Reply from Mastodon.social**
|
||||
- Should appear in Solar Network
|
||||
|
||||
### Test with Other Instances
|
||||
|
||||
- **Pleroma**: Similar to Mastodon, good for testing
|
||||
- **Lemmy**: For testing community features (later)
|
||||
- **Pixelfed**: For testing media posts
|
||||
- **PeerTube**: For testing video content (later)
|
||||
|
||||
## Part 7: Verification Checklist
|
||||
|
||||
### Self-Hosted Instance Tests
|
||||
|
||||
- [ ] WebFinger returns correct actor links
|
||||
- [ ] Actor profile has all required fields
|
||||
- [ ] Follow from Mastodon to Solar Network works
|
||||
- [ ] Follow from Solar Network to Mastodon works
|
||||
- [ ] Accept activity sent back to Mastodon
|
||||
- [ ] Posts from Solar Network appear in Mastodon timeline
|
||||
- [ ] Posts from Mastodon appear in Solar Network database
|
||||
- [ ] Likes from Mastodon appear in Solar Network
|
||||
- [ ] Replies from Mastodon appear in Solar Network
|
||||
- [ ] Keys are properly generated and stored
|
||||
- [ ] HTTP signatures are correctly verified
|
||||
- [ ] Outbox returns public posts
|
||||
|
||||
### Real Instance Tests
|
||||
|
||||
- [ ] Domain is publicly accessible
|
||||
- [ ] HTTPS is working (or HTTP for local testing)
|
||||
- [ ] WebFinger works with your domain
|
||||
- [ ] Actor is discoverable from other instances
|
||||
- [ ] Posts federate to public instances
|
||||
- [ ] Users can follow across instances
|
||||
- [ ] Timelines show federated content
|
||||
|
||||
## Part 8: Monitoring During Tests
|
||||
|
||||
### Check Solar Network Logs
|
||||
|
||||
```bash
|
||||
# Follow logs in real-time
|
||||
dotnet run --project DysonNetwork.Sphere | grep -i activitypub
|
||||
```
|
||||
|
||||
### Check Mastodon Logs
|
||||
|
||||
```bash
|
||||
docker-compose -f docker-compose.mastodon-test.yml logs -f web | grep -i federation
|
||||
```
|
||||
|
||||
### Monitor Database Activity
|
||||
|
||||
```bash
|
||||
# Watch activity table
|
||||
watch -n 2 'psql -d dyson_network -c "SELECT type, status, created_at FROM fediverse_activities ORDER BY created_at DESC LIMIT 10;"'
|
||||
```
|
||||
|
||||
### Check Network Traffic
|
||||
|
||||
```bash
|
||||
# Monitor HTTP requests
|
||||
tcpdump -i lo port 5000 or port 3001 -A
|
||||
```
|
||||
|
||||
## Part 9: Advanced Testing
|
||||
|
||||
### Test HTTP Signature Fallbacks
|
||||
|
||||
Test with various signature headers:
|
||||
|
||||
```bash
|
||||
# With Date header
|
||||
curl -H "Date: $(date -u +%a,\ %d\ %b\ %Y\ %T\ GMT)" ...
|
||||
|
||||
# With Digest header
|
||||
curl -H "Digest: SHA-256=$(echo -n '{}' | openssl dgst -sha256 -binary | base64)" ...
|
||||
|
||||
# Multiple signed headers
|
||||
curl -H "Signature: keyId=\"...\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest\",signature=\"...\"" ...
|
||||
```
|
||||
|
||||
### Test Rate Limiting
|
||||
|
||||
Send multiple requests quickly:
|
||||
|
||||
```bash
|
||||
for i in {1..10}; do
|
||||
curl -X POST http://solar.local:5000/activitypub/actors/solaruser/inbox \
|
||||
-H "Content-Type: application/activity+json" \
|
||||
-d '{"type":"Create",...}'
|
||||
done
|
||||
```
|
||||
|
||||
### Test Large Posts
|
||||
|
||||
Send post with attachments:
|
||||
|
||||
```bash
|
||||
curl -X POST http://solar.local:5000/api/posts \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"content": "A post with an image",
|
||||
"attachments": [{"id": "file-id"}],
|
||||
"visibility": 0
|
||||
}'
|
||||
```
|
||||
|
||||
## Part 10: Cleanup
|
||||
|
||||
### Stop Test Instances
|
||||
|
||||
```bash
|
||||
# Stop Mastodon
|
||||
docker-compose -f docker-compose.mastodon-test.yml down
|
||||
|
||||
# Stop GoToSocial
|
||||
docker-compose -f docker-compose.gotosocial.yml down
|
||||
|
||||
# Remove data volumes
|
||||
docker-compose -f docker-compose.mastodon-test.yml down -v
|
||||
```
|
||||
|
||||
### Reset Solar Network Database
|
||||
|
||||
```bash
|
||||
# Warning: This deletes all data!
|
||||
cd DysonNetwork.Sphere
|
||||
dotnet ef database drop
|
||||
dotnet ef database update
|
||||
```
|
||||
|
||||
### Remove /etc/hosts Entries
|
||||
|
||||
```bash
|
||||
sudo nano /etc/hosts
|
||||
|
||||
# Remove these lines:
|
||||
# 127.0.0.1 mastodon.local
|
||||
# 127.0.0.1 solar.local
|
||||
# 127.0.0.1 gotosocial.local
|
||||
```
|
||||
|
||||
## Next Steps After Testing
|
||||
|
||||
1. **Fix any issues found during testing**
|
||||
2. **Add retry logic for failed deliveries**
|
||||
3. **Implement activity queue for async processing**
|
||||
4. **Add monitoring and metrics**
|
||||
5. **Test with more instances (Pleroma, Pixelfed, etc.)**
|
||||
6. **Add support for more activity types**
|
||||
7. **Improve error handling and logging**
|
||||
8. **Add admin interface for managing federation**
|
||||
|
||||
## Useful Tools
|
||||
|
||||
### ActivityPub Testing Tools
|
||||
- [ActivityPub Playground](https://swicth.github.io/activity-pub-playground/)
|
||||
- [FediTest](https://feditest.com/)
|
||||
- [FediVerse.net](https://fedi.net/)
|
||||
|
||||
### HTTP Testing
|
||||
- [curl](https://curl.se/)
|
||||
- [httpie](https://httpie.io/)
|
||||
- [Postman](https://www.postman.com/)
|
||||
|
||||
### JSON Inspection
|
||||
- [jq](https://stedolan.github.io/jq/)
|
||||
- [jsonpath.com](https://jsonpath.com/)
|
||||
|
||||
### Network Debugging
|
||||
- [Wireshark](https://www.wireshark.org/)
|
||||
- [tcpdump](https://www.tcpdump.org/)
|
||||
|
||||
## References
|
||||
|
||||
- [ActivityPub W3C Spec](https://www.w3.org/TR/activitypub/)
|
||||
- [HTTP Signatures Draft](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures)
|
||||
- [WebFinger RFC 7033](https://tools.ietf.org/html/rfc7033)
|
||||
- [Mastodon Federation Documentation](https://docs.joinmastodon.org/admin/federation/)
|
||||
Reference in New Issue
Block a user