- keys.py: Generate/load RSA-2048 keypairs, sign activities - setup_keys.py: CLI to generate keys - Real RsaSignature2017 signing (falls back to placeholder if no keys) - Public key included in actor profile - Private keys gitignored 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
133 lines
3.4 KiB
Markdown
133 lines
3.4 KiB
Markdown
# 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
|
|
|
|
# Generate signing keys (required for federation)
|
|
python setup_keys.py
|
|
|
|
# Start server
|
|
python server.py
|
|
```
|
|
|
|
## Key Setup
|
|
|
|
ActivityPub requires RSA keys for signing activities. Generate them:
|
|
|
|
```bash
|
|
# Local
|
|
python setup_keys.py
|
|
|
|
# Or with custom paths
|
|
python setup_keys.py --data-dir /data/l2 --user giles
|
|
|
|
# In Docker, exec into container or mount volume
|
|
docker exec -it <container> python setup_keys.py
|
|
```
|
|
|
|
Keys are stored in `$ARTDAG_DATA/keys/`:
|
|
- `{username}.pem` - Private key (chmod 600, NEVER share)
|
|
- `{username}.pub` - Public key (included in actor profile)
|
|
|
|
**Important**: Private keys are gitignored. Back them up securely. Losing them invalidates all your signatures.
|
|
|
|
## 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
|
|
```
|