feat: L2 ActivityPub server

- Registry for owned assets
- ActivityPub endpoints (webfinger, actor, inbox, outbox)
- Create activities with signatures
- Record L1 runs as owned assets with provenance
- Federation support (followers, inbox)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gilesb
2026-01-07 11:32:43 +00:00
commit da55bda1a5
4 changed files with 569 additions and 0 deletions

108
README.md Normal file
View File

@@ -0,0 +1,108 @@
# Art DAG L2 Server - ActivityPub
Ownership registry and ActivityPub federation for Art DAG.
## What it does
- **Registry**: Maintains owned assets with content hashes
- **Activities**: Creates signed ownership claims (Create activities)
- **Federation**: ActivityPub endpoints for follow/share
- **L1 Integration**: Records completed L1 runs as owned assets
## Setup
```bash
pip install -r requirements.txt
# Configure (optional - defaults shown)
export ARTDAG_DOMAIN=artdag.rose-ash.com
export ARTDAG_USER=giles
export ARTDAG_DATA=~/.artdag/l2
export ARTDAG_L1=http://localhost:8100
# Start server
python server.py
```
## API Endpoints
### Server Info
| Method | Path | Description |
|--------|------|-------------|
| GET | `/` | Server info |
### ActivityPub
| Method | Path | Description |
|--------|------|-------------|
| GET | `/.well-known/webfinger?resource=acct:user@domain` | Actor discovery |
| GET | `/users/{username}` | Actor profile |
| GET | `/users/{username}/outbox` | Published activities |
| POST | `/users/{username}/inbox` | Receive activities |
| GET | `/users/{username}/followers` | Followers list |
| GET | `/objects/{content_hash}` | Get object by hash |
### Registry
| Method | Path | Description |
|--------|------|-------------|
| GET | `/registry` | Full registry |
| GET | `/registry/{name}` | Get asset by name |
| POST | `/registry` | Register new asset |
| POST | `/registry/record-run` | Record L1 run as owned asset |
## Example Usage
### Register an asset
```bash
curl -X POST http://localhost:8200/registry \
-H "Content-Type: application/json" \
-d '{
"name": "my-video",
"content_hash": "abc123...",
"asset_type": "video",
"tags": ["art", "generated"]
}'
```
### Record an L1 run
```bash
curl -X POST http://localhost:8200/registry/record-run \
-H "Content-Type: application/json" \
-d '{
"run_id": "uuid-from-l1",
"output_name": "my-rendered-video"
}'
```
### Discover actor (WebFinger)
```bash
curl "http://localhost:8200/.well-known/webfinger?resource=acct:giles@artdag.rose-ash.com"
```
### Get actor profile
```bash
curl -H "Accept: application/activity+json" http://localhost:8200/users/giles
```
## Data Storage
Data stored in `~/.artdag/l2/`:
- `registry.json` - Asset registry
- `activities.json` - Signed activities
- `actor.json` - Actor profile
- `followers.json` - Followers list
## Architecture
```
L2 Server (port 8200)
├── POST /registry → Register asset → Create activity → Sign
├── POST /registry/record-run → Fetch L1 run → Register output
│ │
│ └── GET L1_SERVER/runs/{id}
├── GET /users/{user}/outbox → Return signed activities
└── POST /users/{user}/inbox → Receive Follow requests
```